Linux_SDK_V0.9.5

This commit is contained in:
thead_admin
2022-09-13 10:34:38 +08:00
commit b68c608415
187 changed files with 24398 additions and 0 deletions

21
.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
/.auto.deps
*.tmp
*.bak
*.depend
*.o
*.a
*.o.d
*.o.cmd
*.a.cmd
*.ko.cmd
*.ko
*.mod
*.mod.c
*.mod.cmd
*.order
*.orig
*.log
Module.symvers
modules.order
output/
obj/

54
Makefile Normal file
View File

@@ -0,0 +1,54 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
include build.param
all: info common platform tests examples
info:
@echo $(BUILD_LOG_START)
@echo " ========== Build Info =========="
@echo " Platform: "$(PLATFORM)
@echo " ROOT_DIR: "$(ROOT_DIR)
@echo $(BUILD_LOG_END)
common:
@echo $(BUILD_LOG_START)
make -C src/common
@echo $(BUILD_LOG_END)
platform: common
@echo $(BUILD_LOG_START)
make -C src/platform
@echo $(BUILD_LOG_END)
libs: platform
@echo $(BUILD_LOG_START)
make -C src/lib_camera
@echo $(BUILD_LOG_END)
tests: platform libs
@echo $(BUILD_LOG_START)
make -C tests
@echo $(BUILD_LOG_END)
examples: platform libs
@echo $(BUILD_LOG_START)
make -C examples
@echo $(BUILD_LOG_END)
clean:
rm -rf .obj
make -C src/common/ clean
make -C src/platform/ clean
make -C src/lib_camera clean
make -C tests/ clean
make -C examples/ clean
.PHONY: clean all info common platform tests examples

8
README.md Normal file
View File

@@ -0,0 +1,8 @@
# How to get the code
- git clone git@gitlab.alibaba-inc.com:thead-linux/csi_hal.git
# How to build
- https://yuque.antfin.com/occ/software/fhcekb
# Description
- Maintainer: Lu Chongzhi (chongzhi.lcz@alibaba-inc.com)

63
build.param Normal file
View File

@@ -0,0 +1,63 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
BUILD_LOG_START="\n\033[47;30m>>> $(MODULE_NAME) $@ begin >>>\033[0m"
BUILD_LOG_END ="\033[47;30m<<< $(MODULE_NAME) $@ end <<<\033[0m"
PLATFORM ?= simulator
ROOT_DIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
SO_LIB_DIR=lib_so
ifeq ($(PLATFORM),simulator)
CFLAGS := -O0 -g -Werror -fPIC -DPLATFORM_SIMULATOR
else
CFLAGS := -O2 -g -Werror -fPIC
endif
LFLAGS := -no-pie
LIBS := -L$(ROOT_DIR)/output/common \
-L$(ROOT_DIR)/output/hal
ifeq ($(PLATFORM),light)
INCLUDE := -I$(ROOT_DIR)/include/common \
-I$(ROOT_DIR)/include/hal \
-I$(ROOT_DIR)/include/lib_camera \
-I$(ROOT_DIR)/src/lib_camera/camera_action/include\
-I$(ROOT_DIR)/examples/camera/camera_demo3_srcs \
-I$(ROOT_DIR)/src/lib_camera \
-I$(ROOT_DIR)/../recipe-sysroot/usr/include/csi_hal/
else
INCLUDE := -I$(ROOT_DIR)/include/common \
-I$(ROOT_DIR)/include/hal \
-I$(ROOT_DIR)/include/lib_camera \
-I$(ROOT_DIR)/src/lib_camera/camera_action/include
endif
ifeq ($(PLATFORM),simulator)
CC := gcc
CXX := g++
CPP := g++
AR := ar
LD := ld
RAN := ranlib
LIBOPENCV_INC = $(shell pkg-config --cflags opencv)
LIBOPENCV_LIBS = $(shell pkg-config --libs opencv)
else ifeq ($(PLATFORM),light)
# PARAM_FILE = ../.param
# -include $(PARAM_FILE)
test = $(shell if [ -f "../.param" ]; then echo "exist"; else echo "noexist"; fi)
ifeq ("$(test)", "exist")
-include ../.param
endif
else
$(error PLATFORM undefined)
endif

107
common_target.mk Normal file
View File

@@ -0,0 +1,107 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
OBJS_1 = $(SRCS_1:.c=.o)
$(TARGET_1): $(OBJS_1) $(PREPARE)
@mkdir -p $(OUTPUT_DIR)
@echo ">>> Linking" $@ "..."
$(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_1))) -Wl,--start-group $(LIBS) $(LIBS_1) -Wl,--end-group
cp $@ $(OUTPUT_DIR)
$(OBJS_1): %.o:%.c
@mkdir -p .obj
@echo ">>> Compiling" $< "..."
$(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $<
OBJS_2 = $(SRCS_2:.c=.o)
$(TARGET_2): $(OBJS_2) $(PREPARE)
@mkdir -p $(OUTPUT_DIR)
@echo ">>> Linking" $@ "..."
$(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_2))) -Wl,--start-group $(LIBS) $(LIBS_2) -Wl,--end-group
cp $@ $(OUTPUT_DIR)
$(OBJS_2): %.o:%.c
@mkdir -p .obj
@echo ">>> Compiling" $< "..."
$(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $<
OBJS_3 = $(SRCS_3:.c=.o)
$(TARGET_3): $(OBJS_3) $(PREPARE)
@mkdir -p $(OUTPUT_DIR)
@echo ">>> Linking" $@ "..."
$(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_3))) -Wl,--start-group $(LIBS) $(LIBS_3) -Wl,--end-group
cp $@ $(OUTPUT_DIR)
$(OBJS_3): %.o:%.c
@mkdir -p .obj
@echo ">>> Compiling" $< "..."
$(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $<
OBJS_4 = $(SRCS_4:.c=.o)
$(TARGET_4): $(OBJS_4) $(PREPARE)
@mkdir -p $(OUTPUT_DIR)
@echo ">>> Linking" $@ "..."
$(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_4))) -Wl,--start-group $(LIBS) $(LIBS_4) -Wl,--end-group
cp $@ $(OUTPUT_DIR)
$(OBJS_4): %.o:%.c
@mkdir -p .obj
@echo ">>> Compiling" $< "..."
$(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $<
OBJS_5 = $(SRCS_5:.c=.o)
$(TARGET_5): $(OBJS_5) $(PREPARE)
@mkdir -p $(OUTPUT_DIR)
@echo ">>> Linking" $@ "..."
$(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_5))) -Wl,--start-group $(LIBS) $(LIBS_5) -Wl,--end-group
cp $@ $(OUTPUT_DIR)
$(OBJS_5): %.o:%.c
@mkdir -p .obj
@echo ">>> Compiling" $< "..."
$(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $<
OBJS_6 = $(SRCS_6:.c=.o)
$(TARGET_6): $(OBJS_6) $(PREPARE)
@mkdir -p $(OUTPUT_DIR)
@echo ">>> Linking" $@ "..."
$(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_6))) -Wl,--start-group $(LIBS) $(LIBS_6) -Wl,--end-group
cp $@ $(OUTPUT_DIR)
$(OBJS_6): %.o:%.c
@mkdir -p .obj
@echo ">>> Compiling" $< "..."
$(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $<
OBJS_7 = $(SRCS_7:.c=.o)
$(TARGET_7): $(OBJS_7) $(PREPARE)
@mkdir -p $(OUTPUT_DIR)
@echo ">>> Linking" $@ "..."
$(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_7))) -Wl,--start-group $(LIBS) $(LIBS_7) -Wl,--end-group
cp $@ $(OUTPUT_DIR)
$(OBJS_7): %.o:%.c
@mkdir -p .obj
@echo ">>> Compiling" $< "..."
$(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $<
OBJS_8 = $(SRCS_8:.c=.o)
$(TARGET_8): $(OBJS_8) $(PREPARE)
@mkdir -p $(OUTPUT_DIR)
@echo ">>> Linking" $@ "..."
$(CC) $(LFLAGS) -o $@ $(addprefix .obj/,$(notdir $(OBJS_8))) -Wl,--start-group $(LIBS) $(LIBS_8) -Wl,--end-group
cp $@ $(OUTPUT_DIR)
$(OBJS_8): %.o:%.c
@mkdir -p .obj
@echo ">>> Compiling" $< "..."
$(CC) $(CFLAGS) $(INCLUDE) -c -o .obj/$(notdir $@) $<

52
examples/Makefile Normal file
View File

@@ -0,0 +1,52 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
DIR_TO_ROOT=..
include $(DIR_TO_ROOT)/build.param
ALL_TARGETS := common camera frame
ifeq ($(PLATFORM),simulator)
ALL_TARGETS += vdec venc
endif
all: $(ALL_TARGETS)
common:
@echo $(BUILD_LOG_START)
make -C common/
@echo $(BUILD_LOG_END)
camera:
@echo $(BUILD_LOG_START)
make -C camera/
@echo $(BUILD_LOG_END)
frame:
@echo $(BUILD_LOG_START)
make -C frame/
@echo $(BUILD_LOG_END)
vdec:
@echo $(BUILD_LOG_START)
make -C vdec/
@echo $(BUILD_LOG_END)
venc:
@echo $(BUILD_LOG_START)
make -C venc/
@echo $(BUILD_LOG_END)
clean:
make -C common/ clean
make -C camera/ clean
make -C frame/ clean
make -C vdec/ clean
make -C venc/ clean
rm -rf $(DIR_TO_ROOT)/output/examples/resource
.PHONY: clean all common camera frame vdec venc

5
examples/camera/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
camera_demo1
camera_demo2
camera_demo3
camera_demo4
camera_demo5

85
examples/camera/Makefile Normal file
View File

@@ -0,0 +1,85 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
DIR_TO_ROOT=../..
include $(DIR_TO_ROOT)/build.param
CFLAGS += -Wno-error=unused-result -Icamera_demo3_srcs -I./camera_demo3_srcs -I$(DIR_TO_ROOT)/src/lib_camera/
LIBS += -lhal_common -lhal_camera -lhal_platform -lpthread -lcamera_action
OUTPUT_DIR := $(DIR_TO_ROOT)/output/examples/camera
PREPARE := lib_camera
ifeq ($(PLATFORM),light)
CFLAGS += -I$(VISYS_SYM_PATH)/usr/include/plink/
CFLAGS += -I$(VISYS_SYM_PATH)/usr/include/vidmem/
LIBS += -lstdc++ -lpthread
LIBS += -lvmem -lplink
endif
ifeq ($(PLATFORM),simulator)
LIBS += -lcamera_platform -lapp_utilities -lcamera_utilities $(LIBOPENCV_LIBS) -lstdc++
CFLAGS += $(LIBOPENCV_INC) -I ./opencv
PREPARE += opencv
endif
TARGET_1 := camera_demo1
SRCS_1 = camera_demo1.c
TARGET_2 := camera_demo2
SRCS_2 = camera_demo2.c
TARGET_3 := camera_demo3
SRCS_3 := camera_demo3.c $(wildcard camera_demo3_srcs/*.c)
LIBS_3 += -lcurses
TARGET_4 := camera_demo4
SRCS_4 = camera_demo4.c
TARGET_5 := camera_test1
SRCS_5 = camera_test1.c
TARGET_6 := cam_demo_simple
SRCS_6 = cam_demo_simple.c camera_frame_display.c
TARGET_7 := cam_demo_ir
SRCS_7 = cam_demo_ir.c camera_frame_display.c
TARGET_8 := cam_demo_multi
SRCS_8 = cam_demo_multi.c camera_frame_display.c
ifeq ($(PLATFORM),simulator)
TARGET_ALL := $(TARGET_1) $(TARGET_2) $(TARGET_3) $(TARGET_4)
else
TARGET_ALL := $(TARGET_1) $(TARGET_2) $(TARGET_3) $(TARGET_5) $(TARGET_6) $(TARGET_7) $(TARGET_8)
endif
all: $(TARGET_ALL)
cp run_camera_demo3.sh $(OUTPUT_DIR)
cp camera_demo3.conf $(OUTPUT_DIR)
lib_camera:
make -C $(DIR_TO_ROOT)/src/lib_camera
opencv:
make -C opencv
clean:
rm -rf .obj
rm -f $(TARGET_1) $(OUTPUT_DIR)/$(TARGET_1)
rm -f $(TARGET_2) $(OUTPUT_DIR)/$(TARGET_2)
rm -f $(TARGET_3) $(OUTPUT_DIR)/$(TARGET_3)
rm -f $(TARGET_3) $(OUTPUT_DIR)/run_camera_demo3.sh
rm -f $(TARGET_3) $(OUTPUT_DIR)/camera_demo3.conf
rm -f $(TARGET_4) $(OUTPUT_DIR)/$(TARGET_4)
rm -f $(TARGET_5) $(OUTPUT_DIR)/$(TARGET_5)
make -C ./opencv clean
include $(DIR_TO_ROOT)/common_target.mk
.PHONY: opencv clean all

View File

@@ -0,0 +1,678 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "pthread.h"
#include <sys/mman.h>
#define LOG_LEVEL 2
#define LOG_PREFIX "cam_demo_ir"
#include <syslog.h>
#include <csi_frame.h>
#include <csi_camera.h>
#include "csi_camera_dev_api.h"
#define TEST_DEVICE_NAME "/dev/video12"
typedef struct frame_fps {
uint64_t frameNumber;
struct timeval initTick;
float fps;
} frame_fps_t;
static void dump_camera_meta(csi_frame_s *frame);
static void dump_camera_frame(csi_frame_s *frame, int ch_id);
typedef struct event_queue_item{
struct csi_camera_event evet;
struct event_queue_item *next;
}event_queue_item_t;
typedef struct channel_handle_ctx{
struct event_queue{
event_queue_item_t *head;
event_queue_item_t *tail;
int exit;
pthread_mutex_t mutex;
pthread_cond_t cond;
}event_queue;
csi_cam_handle_t cam_handle;
pthread_t chan_thread;
int frame_num;
}channel_handle_ctx_t;
static event_queue_item_t *dequeue_event(channel_handle_ctx_t *ctx)
{
event_queue_item_t *ev = ctx->event_queue.head;
pthread_mutex_lock(&ctx->event_queue.mutex);
if(!ev)
{
pthread_mutex_unlock(&ctx->event_queue.mutex);
return NULL;
}
if(ev == ctx->event_queue.tail)
ctx->event_queue.tail = NULL;
ctx->event_queue.head = ev->next;
pthread_mutex_unlock(&ctx->event_queue.mutex);
return ev;
}
static int test_flag =0;
static void enqueue_event(channel_handle_ctx_t *ctx,event_queue_item_t * item)
{
if(!item || !ctx)
return;
item->next = NULL;
LOG_D("%s enter \n", __func__);
pthread_mutex_lock(&ctx->event_queue.mutex);
if (ctx->event_queue.tail) {
ctx->event_queue.tail->next = item;
} else {
ctx->event_queue.head = item;
// pthread_cond_broadcast(&ctx->cond.cond);
}
ctx->event_queue.tail = item;
pthread_mutex_unlock(&ctx->event_queue.mutex);
}
static void* camera_channle_process(void* arg)
{
struct timeval init_time, cur_time;
frame_fps_t demo_fps;
csi_frame_s frame;
memset(&init_time, 0, sizeof(init_time));
memset(&cur_time, 0, sizeof(cur_time));
channel_handle_ctx_t * ctx = (channel_handle_ctx_t *)arg;
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
LOG_D("Channel process running........\n");
while(ctx->event_queue.exit == 0)
{
event_queue_item_t *item = dequeue_event(ctx);
if(item==NULL)
{
continue;
}
switch (item->evet.type) {
case CSI_CAMERA_EVENT_TYPE_CHANNEL0:
case CSI_CAMERA_EVENT_TYPE_CHANNEL1:
switch (item->evet.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
csi_camera_channel_id_e ch_id = item->evet.type-CSI_CAMERA_EVENT_TYPE_CHANNEL0+CSI_CAMERA_CHANNEL_0;
int read_frame_count = csi_camera_get_frame_count(ctx->cam_handle,
ch_id);
for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(ctx->cam_handle, ch_id, &frame, timeout);
demo_fps.frameNumber++;
ctx->frame_num++;
dump_camera_meta(&frame);
if(test_flag ==0)
{
dump_camera_frame(&frame,ch_id);
}
// csi_camera_frame_unlock(cam_handle, &frame);
csi_camera_put_frame(&frame);
csi_frame_release(&frame);
}
unsigned long diff;
if (init_time.tv_usec == 0)
gettimeofday(&init_time,0);//osGetTick();
gettimeofday(&cur_time, 0);
diff = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec;
if (diff != 0)
demo_fps.fps = (float)demo_fps.frameNumber / diff * 1000000.0f;
LOG_O("ch id:%d read_frame_count = %d, frame_count = %d, fps = %.2f diff = %ld\n",ch_id, read_frame_count, ctx->frame_num, demo_fps.fps, diff);
break;
}
default:
break;
}
default:
break;
}
free(item);
}
LOG_O("exit\n");
pthread_exit(0);
}
channel_handle_ctx_t channel_ctx[2];
/***********************DSP ALGO *******************************/
typedef struct cb_context{
int id;
csi_cam_handle_t cam_handle;
int dsp_id;
int dsp_path;
void *ref_buf;
int buf_size;
}cb_context_t;
typedef struct cb_args{
char lib_name[8];
char setting[16];
uint32_t frame_id;
uint64_t timestap;
uint32_t temp_projector; //投射器温度
uint32_t temp_sensor; //sensor 温度
}cb_args_t;
cb_context_t cb_context[2];
void dsp_algo_result_cb(void*context,void*arg)
{
cb_context_t *ctx = (cb_context_t *)context;
cb_args_t *cb_args= (cb_args_t*)arg;
char update_setting[16];
struct timeval times_value;
uint32_t frame_id = cb_args->frame_id;
uint64_t frame_timestap = cb_args->timestap;
times_value.tv_sec = cb_args->timestap/1000000;
times_value.tv_usec = cb_args->timestap%1000000;
LOG_O("cb:%d,%s,setting:%s,frame :%d,timestad:(%ld s,%ld us)\n",ctx->id,cb_args->lib_name,cb_args->setting,
frame_id,times_value.tv_sec,times_value.tv_usec);
LOG_O("temperate projector:%d,sensor:%d\n",cb_args->temp_projector,cb_args->temp_sensor);
if(test_flag!=0)
{
sprintf(update_setting, "update_%d", frame_id);
csi_camera_update_dsp_algo_setting(ctx->cam_handle,ctx->dsp_id,ctx->dsp_path,update_setting);
if(frame_id%20==0)
{
void *replace_buf;
*((uint32_t*)ctx->ref_buf) = frame_id;
csi_camera_update_dsp_algo_buf(ctx->cam_handle, ctx->dsp_id,ctx->dsp_path,ctx->ref_buf,&replace_buf);
LOG_D("cb:%d,old buffer:0x%llx,new buffer:0x%llx\n",ctx->id,ctx->ref_buf,replace_buf);
ctx->ref_buf = replace_buf;
}
}
}
static void usage(void)
{
printf(" 1 : video id cases\n");
printf(" 2 : [0]dump frame or [1] algo loop test\n");
printf(" 3 : frame num to stop ,0: for not stop\n");
printf(" 4 : channel 0 algo\n");
printf(" 5 : channel 1 algo\n");
}
int main(int argc, char *argv[])
{
uint32_t i;
bool running = true;
csi_camera_info_s camera_info;
frame_fps_t demo_fps;
char *algo_1;
char *algo_2;
int video_id = -1;
char dev_name[64];
int frame_num = 0;
algo_2 = "dsp1_dummy_algo_flo";
algo_1 = "dsp1_dummy_algo_flo_1";
switch(argc)
{
case 0:
case 1:
LOG_E("input ERROR:vidoe id is mandatory\n");
usage();
return -1;
case 6:
algo_2 = (argv[5]);
case 5:
algo_1 = (argv[4]);
case 4:
frame_num = atoi(argv[3]);
case 3:
test_flag = atoi(argv[2]);
case 2:
video_id = atoi(argv[1]);
break;
default:
LOG_E("input ERROR:too many param\n");
usage();
return -1;
}
LOG_O("Demo: video id:%d,test type:%d,frame number:%d,algo1:%s,algo2:%s\n",video_id,test_flag,frame_num,algo_1,algo_2);
sprintf(dev_name, "/dev/video%d", video_id);
memset(&demo_fps, 0, sizeof(demo_fps));
struct timeval init_time, cur_time;
memset(&init_time, 0, sizeof(init_time));
memset(&cur_time, 0, sizeof(cur_time));
// 获取设备中所有的Camera
struct csi_camera_infos camera_infos;
memset(&camera_infos, 0, sizeof(camera_infos));
csi_camera_query_list(&camera_infos);
LOG_O("csi_camera_query_list() OK\n");
// 打印所有设备所支持的Camera
for (i = 0; i < camera_infos.count; i++) {
printf("Camera[%d]: camera_name='%s', device_name='%s', bus_info='%s', capabilities=0x%08x\n",
i, camera_infos.info[i].camera_name, camera_infos.info[i].device_name,
camera_infos.info[i].bus_info, camera_infos.info[i].capabilities);
}
/* Camera[0]: camera_name='RGB_Camera', device_name='/dev/video0', bus_info='CSI-MIPI', capabilities=0x00800001
* Camera[1]: camera_name:'Mono_Camera', device_name:'/dev/video8', bus_info='USB', capabilities=0x00000001
*/
bool found_camera = false;
for (i = 0; i < camera_infos.count; i++) {
if (strcmp(camera_infos.info[i].device_name, dev_name) == 0) {
camera_info = camera_infos.info[i];
printf("found device_name:'%s'\n", camera_info.device_name);
found_camera = true;
break;
}
}
if (!found_camera) {
LOG_E("Can't find camera_name:'%s'\n", dev_name);
exit(-1);
}
printf("The caps are:\n");
for (i = 1; i < 0x80000000; i = i << 1) {
switch (camera_info.capabilities & i) {
case CSI_CAMERA_CAP_VIDEO_CAPTURE:
printf("\t Video capture\n");
break;
case CSI_CAMERA_CAP_META_CAPTURE:
printf("\t metadata capture\n");
break;
default:
if (camera_info.capabilities & i) {
printf("\t unknown capabilities(0x%08x)\n", camera_info.capabilities & i);
}
break;
}
}
/* The caps are: Video capture, metadata capture */
// 打开Camera设备获取句柄作为后续操对象
csi_cam_handle_t cam_handle;
csi_camera_open(&cam_handle, camera_info.device_name);
LOG_O("csi_camera_open() OK\n");
// 获取Camera支持的工作模式
struct csi_camera_modes camera_modes;
camera_modes.count = 0;
csi_camera_get_modes(cam_handle, &camera_modes);
LOG_O("csi_camera_get_modes() OK\n");
// 打印camera所支持的所有工作模式
printf(" Camera:'%s' modes are:{\n", dev_name);
for (i = 0; i < camera_modes.count; i++) {
printf("\t mode_id=%d: description:'%s'\n",
camera_modes.modes[i].mode_id, camera_modes.modes[i].description);
}
printf("}\n");
csi_camera_channel_cfg_s chn_cfg;
chn_cfg.chn_id = CSI_CAMERA_CHANNEL_0;
chn_cfg.frm_cnt = 4;
chn_cfg.img_fmt.width = 1080;
chn_cfg.img_fmt.height = 1280;
chn_cfg.img_fmt.pix_fmt = CSI_PIX_FMT_RAW_12BIT;
chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
CSI_CAMERA_CHANNEL_CAPTURE_META;
csi_camera_channel_open(cam_handle, &chn_cfg);
LOG_O("CSI_CAMERA_CHANNEL_0: csi_camera_channel_open() OK\n");
// 打开输出channel_1
chn_cfg.chn_id = CSI_CAMERA_CHANNEL_1;
chn_cfg.frm_cnt = 4;
chn_cfg.img_fmt.width = 1080;
chn_cfg.img_fmt.height = 1280;
chn_cfg.img_fmt.pix_fmt = CSI_PIX_FMT_RAW_12BIT;
chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
CSI_CAMERA_CHANNEL_CAPTURE_META;
csi_camera_channel_open(cam_handle, &chn_cfg);
LOG_O("CSI_CAMERA_CHANNEL_1: csi_camera_channel_open() OK\n");
// 订阅Event
csi_cam_event_handle_t event_handle;
csi_camera_create_event(&event_handle, cam_handle);
struct csi_camera_event_subscription subscribe;
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
csi_camera_subscribe_event(event_handle, &subscribe);
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CHANNEL0; // 订阅Channel0的FRAME_READY事件
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
csi_camera_subscribe_event(event_handle, &subscribe);
memset(&channel_ctx[0],0x0,sizeof(channel_handle_ctx_t));
channel_ctx[0].cam_handle = cam_handle;
pthread_mutex_init(&channel_ctx[0].event_queue.mutex,NULL);
pthread_cond_init(&channel_ctx[0].event_queue.cond,NULL);
pthread_create(&channel_ctx[0].chan_thread,NULL,camera_channle_process,&channel_ctx[0]);
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CHANNEL1; // 订阅Channel0的FRAME_READY事件
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
csi_camera_subscribe_event(event_handle, &subscribe);
memset(&channel_ctx[1],0x0,sizeof(channel_handle_ctx_t));
channel_ctx[1].cam_handle = cam_handle;
pthread_mutex_init(&channel_ctx[1].event_queue.mutex,NULL);
pthread_cond_init(&channel_ctx[1].event_queue.cond,NULL);
pthread_create(&channel_ctx[1].chan_thread,NULL,camera_channle_process,&channel_ctx[1]);
LOG_O("Event subscript OK\n");
cb_context[0].id=0;
cb_context[0].cam_handle = cam_handle;
cb_context[0].dsp_id = 1;
cb_context[0].dsp_path = 3;
char test_set[16]="init";
cb_context[0].buf_size = 1920*1080;
cb_context[0].ref_buf=NULL;
csi_camera_dsp_algo_param_t algo_param_1={
.algo_name = algo_1,
.algo_cb.cb = dsp_algo_result_cb,
.algo_cb.context = &cb_context[0],
.algo_cb.arg_size = sizeof(cb_args_t),
.sett_ptr = test_set,
.sett_size =sizeof(test_set),
.extra_buf_num =1,
.extra_buf_sizes = &cb_context[0].buf_size,
.extra_bufs = &cb_context[0].ref_buf,
};
if(csi_camera_set_dsp_algo_param(cam_handle, cb_context[0].dsp_id,cb_context[0].dsp_path, &algo_param_1))
{
LOG_E("set DSP algo fail\n");
}
cb_context[1].id=1;
cb_context[1].cam_handle = cam_handle;
cb_context[1].dsp_id = 1;
cb_context[1].dsp_path = 4;
cb_context[1].buf_size = 1920*1080;
cb_context[1].ref_buf=NULL;
csi_camera_dsp_algo_param_t algo_param_2={
.algo_name = algo_2,
.algo_cb.cb = dsp_algo_result_cb,
.algo_cb.context = &cb_context[1],
.algo_cb.arg_size = sizeof(cb_args_t),
.sett_ptr = test_set,
.sett_size =sizeof(test_set),
.extra_buf_num =1,
.extra_buf_sizes = &cb_context[1].buf_size,
.extra_bufs = &cb_context[1].ref_buf,
};
if(csi_camera_set_dsp_algo_param(cam_handle, cb_context[1].dsp_id,cb_context[1].dsp_path, &algo_param_2))
{
LOG_E("set DSP algo fail\n");
}
csi_camera_floodlight_led_set_flash_bright(cam_handle, 500); //500ma
csi_camera_projection_led_set_flash_bright(cam_handle, 500); //500ma
csi_camera_projection_led_set_mode(cam_handle, LED_IR_ENABLE);
csi_camera_floodlight_led_set_mode(cam_handle, LED_IR_ENABLE);
csi_camera_led_enable(cam_handle, LED_FLOODLIGHT_PROJECTION);
// 开始从channel中取出准备好的frame
csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_0);
csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_1);
LOG_O("Channel start OK\n");
// 处理订阅的Event
csi_frame_s frame;
event_queue_item_t *event_item;
LOG_O("Starting get frame...\n");
while (running) {
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
event_item = malloc(sizeof( event_queue_item_t));
csi_camera_get_event(event_handle, &event_item->evet, timeout);
LOG_O("event.type = %d, event.id = %d\n",event_item->evet.type, event_item->evet.id);
switch (event_item->evet.type) {
case CSI_CAMERA_EVENT_TYPE_CAMERA:
switch (event_item->evet.id) {
case CSI_CAMERA_EVENT_ERROR:
// do sth.
break;
default:
break;
free(event_item);
break;
}
case CSI_CAMERA_EVENT_TYPE_CHANNEL0:
case CSI_CAMERA_EVENT_TYPE_CHANNEL1:
switch (event_item->evet.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
csi_camera_channel_id_e ch_id = event_item->evet.type-CSI_CAMERA_EVENT_TYPE_CHANNEL0+CSI_CAMERA_CHANNEL_0;
if(event_item && ch_id<2)
{
enqueue_event(&channel_ctx[ch_id],event_item);
}
break;
}
default:
free(event_item);
break;
}
break;
default:
free(event_item);
break;
}
// LOG_O("stop:%d,frame:(%d,%d)(%llx,%llx)\n",frame_num ,channel_ctx[0].frame_num ,channel_ctx[1].frame_num,&(channel_ctx[0].frame_num),&(channel_ctx[1].frame_num));
if((frame_num >0) &&
(channel_ctx[0].frame_num >frame_num) &&
(channel_ctx[1].frame_num >frame_num))
{
csi_camera_channel_stop(cam_handle, CSI_CAMERA_CHANNEL_0);
csi_camera_channel_stop(cam_handle, CSI_CAMERA_CHANNEL_1);
channel_ctx[0].event_queue.exit = 1;
channel_ctx[1].event_queue.exit = 1;
pthread_join(channel_ctx[0].chan_thread,NULL);
pthread_join(channel_ctx[1].chan_thread,NULL);
running = false;
}
}
// 取消订阅某一个event, 也可以直接调用csi_camera_destory_event结束所有的订阅
subscribe.type = CSI_CAMERA_EVENT_TYPE_CHANNEL0;
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;;
csi_camera_unsubscribe_event(event_handle, &subscribe);
subscribe.type = CSI_CAMERA_EVENT_TYPE_CHANNEL1;
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;;
csi_camera_unsubscribe_event(event_handle, &subscribe);
subscribe.type = CSI_CAMERA_EVENT_TYPE_CAMERA;
subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
csi_camera_unsubscribe_event(event_handle, &subscribe);
csi_camera_destory_event(event_handle);
csi_camera_channel_close(cam_handle, CSI_CAMERA_CHANNEL_0);
csi_camera_close(cam_handle);
}
static void dump_camera_meta(csi_frame_s *frame)
{
int i;
if (frame->meta.type != CSI_META_TYPE_CAMERA)
return;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
csi_camrea_meta_unit_s meta_frame_id,meta_frame_ts;
csi_camera_frame_get_meta_unit(
&meta_frame_id, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
csi_camera_frame_get_meta_unit(
&meta_frame_ts, meta_data, CSI_CAMERA_META_ID_TIMESTAMP);
LOG_O("meta frame id=%d,time stap:(%ld,%ld)\n",
meta_frame_id.int_value,meta_frame_ts.time_value.tv_sec,meta_frame_ts.time_value.tv_usec);
}
static void dump_camera_frame(csi_frame_s *frame, int ch_id)
{
char file[128];
static int file_indx=0;
int size,buf_size;
uint32_t indexd, j;
void *buf[3];
sprintf(file,"demo_save_img_ch_%d_%d", ch_id,file_indx++%6);
int fd = open(file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IROTH);
if(fd == -1) {
LOG_E("%s, %d, open file error!!!!!!!!!!!!!!!\n", __func__, __LINE__);
return ;
}
if (frame->img.type == CSI_IMG_TYPE_DMA_BUF) {
buf_size = frame->img.strides[0]*frame->img.height;
switch(frame->img.pix_format) {
case CSI_PIX_FMT_NV12:
case CSI_PIX_FMT_YUV_SEMIPLANAR_420:
if(frame->img.num_planes ==2)
{
buf_size+=frame->img.strides[1]*frame->img.height/2;
}
else{
LOG_E("img fomrat is not match with frame planes:%d\n",frame->img.num_planes);
return;
}
break;
case CSI_PIX_FMT_YUV_SEMIPLANAR_422:
if(frame->img.num_planes ==2)
{
buf_size+=frame->img.strides[1]*frame->img.height;
}
else{
LOG_E("img fomrat is not match with frame planes:%d\n",frame->img.num_planes);
return;
}
break;
default:
break;
}
buf[0]= mmap(0, buf_size, PROT_READ | PROT_WRITE,
MAP_SHARED, frame->img.dmabuf[0].fds, frame->img.dmabuf[0].offset);
// plane_size[1] = frame->img.strides[1]*frame->img.height;
// printf("frame plane 1 stride:%d,offset:%d\n", frame->img.strides[1],(uint32_t)frame->img.dmabuf[1].offset);
if(frame->img.num_planes ==2)
{
// buf[1] = mmap(0, plane_size[1]/2, PROT_READ | PROT_WRITE,
// MAP_SHARED, frame->img.dmabuf[1].fds, frame->img.dmabuf[1].offset);
buf[1] = buf[0]+frame->img.dmabuf[1].offset;
}
}
else{
buf[0] = frame->img.usr_addr[0];
buf[1] = frame->img.usr_addr[1];
}
LOG_O("save img from :%d, to %s, fmt:%d width:%d stride:%d height:%d\n",frame->img.dmabuf[0].fds, file, frame->img.pix_format , frame->img.width, frame->img.strides[0], frame->img.height);
frame->img.pix_format = CSI_PIX_FMT_RAW_12BIT;
switch(frame->img.pix_format) {
case CSI_PIX_FMT_NV12:
case CSI_PIX_FMT_YUV_SEMIPLANAR_420:
if (frame->img.strides[0] == 0) {
frame->img.strides[0] = frame->img.width;
}
for (j = 0; j < frame->img.height; j++) { //Y
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, frame->img.width);
}
for (j = 0; j < frame->img.height / 2; j++) { //UV
indexd = j*frame->img.strides[0];
write(fd, buf[1] + indexd, frame->img.width);
}
break;
case CSI_PIX_FMT_RGB_INTEVLEAVED_888:
case CSI_PIX_FMT_YUV_TEVLEAVED_444:
size = frame->img.width*3;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_BGR:
case CSI_PIX_FMT_RGB_PLANAR_888:
case CSI_PIX_FMT_YUV_PLANAR_444:
size = frame->img.width * frame->img.height * 3;
write(fd, buf[0], size);
break;
case CSI_PIX_FMT_RAW_8BIT:
size = frame->img.width;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_YUV_TEVLEAVED_422:
case CSI_PIX_FMT_RAW_10BIT:
case CSI_PIX_FMT_RAW_12BIT:
case CSI_PIX_FMT_RAW_14BIT:
case CSI_PIX_FMT_RAW_16BIT:
size = frame->img.width*2;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_YUV_SEMIPLANAR_422:
if (frame->img.strides[0] == 0) {
frame->img.strides[0] = frame->img.width;
}
for (j = 0; j < frame->img.height; j++) { //Y
indexd = j*frame->img.strides[0];
write(fd,buf[0] + indexd, frame->img.width);
}
for (j = 0; j < frame->img.height; j++) { //UV
indexd = j*frame->img.strides[0];
write(fd, buf[1]+ indexd, frame->img.width);
}
break;
default:
LOG_E("%s unsupported format to save\n", __func__);
exit(-1);
break;
}
close(fd);
munmap(buf[0],buf_size);
// munmap(buf[1],plane_size[1]);
LOG_O("%s exit\n", __func__);
}

View File

@@ -0,0 +1,807 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: ShenWuYi <shenwuyi.swy@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define LOG_LEVEL 2
#define LOG_PREFIX "cam_demo_multi"
#include <syslog.h>
#include <csi_frame.h>
#include <csi_camera.h>
#include <csi_camera_dev_api.h>
#ifdef PLATFORM_SIMULATOR
#include "apputilities.h"
#endif
#define MAX_CAM_NUM 3
#define MAX_CHANNEL_NUM 3
static void dump_camera_meta(csi_frame_s *frame);
static void dump_camera_frame(csi_frame_s *frame, csi_pixel_fmt_e fmt, int camera_id);
// extern int csi_camera_frame_unlock(csi_cam_handle_t cam_handle, csi_frame_s *frame);
#define TEST_DEVICE_NAME "/dev/video0"
#define CSI_CAMERA_TRUE 1
#define CSI_CAMERA_FALSE 0
typedef struct frame_fps {
uint64_t frameNumber;
struct timeval initTick;
float fps;
} frame_fps_t;
typedef enum _frame_mode{
FRAME_NONE =0,
FRAME_SAVE_IMG =1,
FRAME_SAVE_STREAM =2,
FRAME_SAVE_DISPLAY,
FRAME_INVALID,
}frame_mode_t;
typedef enum _cam_type{
CAM_TYEP_RGB =0,
CAM_TYEP_IR,
CAM_TYEP_INVALID,
}cam_type_e;
typedef struct _camera_param{
int video_id;
int channel_num;
struct {
int width;
int height;
csi_pixel_fmt_e fmt;
}out_pic[MAX_CHANNEL_NUM];
cam_type_e type;
frame_mode_t mode;
int frames_to_stop;
}camera_param_t;
typedef struct event_queue_item{
struct csi_camera_event evet;
struct event_queue_item *next;
}event_queue_item_t;
typedef struct _camera_ctx{
int cam_id;
pthread_t cam_thread;
int exit;
csi_cam_handle_t cam_handle;
int channel_num;
csi_cam_event_handle_t event_handle;
csi_camera_event_subscription_s event_subscribe;
csi_camera_channel_cfg_s chn_cfg[MAX_CHANNEL_NUM];
void * disaply_plink[MAX_CHANNEL_NUM];
int frame_num;
frame_mode_t frame_mode[MAX_CHANNEL_NUM];
}camera_ctx_t;
int file_id = 0;
extern void *vi_plink_create(csi_camera_channel_cfg_s *chn_cfg);
extern void vi_plink_release(void * plink);
extern void display_camera_frame(void * plink, csi_frame_s *frame);
static void usage(void)
{
printf(" 1 : RGB Camera id \n");
printf(" 2 : RGB Camera id channel num\n");
printf(" 3 : RGB Camera frame mode :0 none ,1 dump enable,2 display \n");
printf(" 4 : RGB Camera frame num :0 not stop ,else frame num to stop \n");
printf(" 5 : IR Camera id \n");
printf(" 6 : IR Camera id channel num\n");
printf(" 7 : IR Camera frame mode :0 none ,1 dump enable,2 display \n");
printf(" 8 : IR Camera frame num :0 not stop ,else frame num to stop \n");
}
void printUsage(char *name)
{
printf("usage: %s [options]\n"
"\n"
" Available options:\n"
" -f fisrt camera device 5 param \n"
" 1:video id 2: channel num 3: camrea type (0->rgb ;1->IR) (mandatory)\n"
" 3: mode【0->none ,1->save image,2->display 】(default 1) \n"
" 4: frame num to stop 【0 not stop】(default 0) \n"
" -s second camera device 5 param)\n"
" same param setting as above)\n"
" -t third camera device 5 param)\n"
" same param setting above)\n"
"\n", name);
}
static int parseParams(int argc, char **argv, camera_param_t *params)
{
int index =0;
params[index].video_id = 2;
params[index].type = CAM_TYEP_RGB;
params[index].channel_num =1;
params[index].out_pic[0].width = 1920;
params[index].out_pic[0].height = 1080;
params[index].out_pic[0].fmt = CSI_PIX_FMT_NV12;
params[index].mode = FRAME_SAVE_IMG;
params[index].frames_to_stop = 0;
index++;
params[index].video_id = 6;
params[index].type = CAM_TYEP_IR;
params[index].channel_num = 2;
params[index].out_pic[0].width = 1080;
params[index].out_pic[0].height = 1280;
params[index].out_pic[0].fmt =CSI_PIX_FMT_RAW_12BIT;
params[index].out_pic[1].width = 1080;
params[index].out_pic[1].height = 1280;
params[index].out_pic[1].fmt =CSI_PIX_FMT_RAW_12BIT;
params[index].mode = FRAME_SAVE_IMG;
params[index].frames_to_stop = 0;
index++;
return index;
}
static void get_system_time(const char *func, int line_num)
{
struct timeval cur_time;
memset(&cur_time, 0, sizeof(cur_time));
gettimeofday(&cur_time, 0);
printf("%s %s line_num = %d, cur_time.tv_sec = %ld, cur_time.tv_usec = %ld\n",
__func__, func, line_num, cur_time.tv_sec, cur_time.tv_usec);
}
static int camera_get_chl_id(int env_type, int *chl_id)
{
if (chl_id == NULL) {
LOG_E("fail to check param chl_id = %p\n", chl_id);
return -1;
}
switch (env_type) {
case CSI_CAMERA_EVENT_TYPE_CHANNEL0:
*chl_id = CSI_CAMERA_CHANNEL_0;
break;
case CSI_CAMERA_EVENT_TYPE_CHANNEL1:
*chl_id = CSI_CAMERA_CHANNEL_1;
break;
case CSI_CAMERA_EVENT_TYPE_CHANNEL2:
*chl_id = CSI_CAMERA_CHANNEL_2;
break;
default:
LOG_D("%s fail to check env_type = %d unsupport\n", env_type);
break;
}
return 0;
}
/***********************DSP ALGO *******************************/
typedef struct cb_context{
int id;
csi_cam_handle_t cam_handle;
int dsp_id;
int dsp_path;
void *ref_buf;
int buf_size;
}cb_context_t;
typedef struct cb_args{
char lib_name[8];
char setting[16];
uint32_t frame_id;
uint64_t timestap;
uint32_t temp_projector; //投射器温度
uint32_t temp_sensor; //sensor 温度
}cb_args_t;
cb_context_t cb_context[2];
void dsp_algo_result_cb(void*context,void*arg)
{
cb_context_t *ctx = (cb_context_t *)context;
cb_args_t *cb_args= (cb_args_t*)arg;
char update_setting[16];
struct timeval times_value;
uint32_t frame_id = cb_args->frame_id;
uint64_t frame_timestap = cb_args->timestap;
times_value.tv_sec = cb_args->timestap/1000000;
times_value.tv_usec = cb_args->timestap%1000000;
LOG_O("cb:%d,%s,setting:%s,frame :%d,timestad:(%ld s,%ld us)\n",ctx->id,cb_args->lib_name,cb_args->setting,
frame_id,times_value.tv_sec,times_value.tv_usec);
LOG_O("temperate projector:%d,sensor:%d\n",cb_args->temp_projector,cb_args->temp_sensor);
// if(test_flag!=0)
{
sprintf(update_setting, "update_%d", frame_id);
csi_camera_update_dsp_algo_setting(ctx->cam_handle,ctx->dsp_id,ctx->dsp_path,update_setting);
if(frame_id%20==0)
{
void *replace_buf;
*((uint32_t*)ctx->ref_buf) = frame_id;
csi_camera_update_dsp_algo_buf(ctx->cam_handle, ctx->dsp_id,ctx->dsp_path,ctx->ref_buf,&replace_buf);
LOG_D("cb:%d,old buffer:0x%llx,new buffer:0x%llx\n",ctx->id,ctx->ref_buf,replace_buf);
ctx->ref_buf = replace_buf;
}
}
}
static void *camera_event_thread(void *arg)
{
int ret = 0;
if (arg == NULL) {
LOG_E("NULL Ptr\n");
pthread_exit(0);
}
camera_ctx_t* ctx = (camera_ctx_t*)arg;
csi_cam_event_handle_t ev_handle = ctx->event_handle;
csi_camera_channel_cfg_s *ch_cfg=NULL;
struct timeval init_time, cur_time;
memset(&init_time, 0, sizeof(init_time));
memset(&cur_time, 0, sizeof(cur_time));
frame_fps_t demo_fps;
memset(&demo_fps, 0, sizeof(demo_fps));
csi_frame_s frame;
if (ev_handle == NULL) {
LOG_E("fail to get ev_handle ev_handle\n");
pthread_exit(0);
}
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
int loop_count = 0;
struct csi_camera_event event;
LOG_O("Theard is runing............\n");
while (ctx->exit==0) {
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
csi_camera_get_event(ev_handle, &event, timeout);
LOG_D("Camera_%d event.type = %d, event.id = %d\n",ctx->cam_id ,event.type, event.id);
switch (event.type) {
case CSI_CAMERA_EVENT_TYPE_CAMERA:
switch (event.id) {
case CSI_CAMERA_EVENT_ERROR:
// do sth.
LOG_E("get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!\n");
break;
case CSI_CAMERA_EVENT_WARNING:
LOG_W("get CAMERA EVENT CSI_CAMERA_EVENT_WRN,RC: %s\n",event.bin);
break;
default:
break;
}
break;
case CSI_CAMERA_EVENT_TYPE_CHANNEL0:
case CSI_CAMERA_EVENT_TYPE_CHANNEL1:
case CSI_CAMERA_EVENT_TYPE_CHANNEL2:
case CSI_CAMERA_EVENT_TYPE_CHANNEL3:
switch (event.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
int chn_id = 0;
ret = camera_get_chl_id(event.type, &chn_id);
if (ret) {
LOG_E("fail to get chl_id = %d\n", chn_id);
continue;
}
ch_cfg = &ctx->chn_cfg[chn_id];
get_system_time(__func__, __LINE__);
int read_frame_count = csi_camera_get_frame_count(ctx->cam_handle,
chn_id);
unsigned long diff;
if (init_time.tv_usec == 0)
gettimeofday(&init_time,0);//osGetTick();
gettimeofday(&cur_time, 0);
diff = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec;
demo_fps.frameNumber++;
if (diff != 0)
demo_fps.fps = (float)demo_fps.frameNumber / diff * 1000000.0f;
LOG_O("cam:%d,channle:%d ,read_frame_count = %d, frame_count = %ld, fps = %.2f diff = %ld\n", ctx->cam_id, chn_id, read_frame_count, demo_fps.frameNumber, demo_fps.fps, diff);
for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(ctx->cam_handle, chn_id, &frame, timeout);
dump_camera_meta(&frame);
if (ctx->frame_mode[chn_id] == FRAME_SAVE_IMG) {
dump_camera_frame(&frame, ch_cfg->img_fmt.pix_fmt, chn_id);
}
if (ctx->disaply_plink && ctx->frame_mode[chn_id]==FRAME_SAVE_DISPLAY) {
frame.img.pix_format = ch_cfg->img_fmt.pix_fmt;
display_camera_frame(ctx->disaply_plink, &frame);
}
csi_camera_put_frame(&frame);
ctx->frame_num++;
}
break;
}
default:
break;
}
break;
default:
break;
}
}
LOG_O("exit!\n");
pthread_exit(0);
}
static void camera_start_all(camera_ctx_t * ctx)
{
camera_ctx_t * cam_ctx = ctx;
int loop_ch;
for(loop_ch=0;loop_ch<cam_ctx->channel_num;loop_ch++)
{
csi_camera_channel_start(cam_ctx->cam_handle, cam_ctx->chn_cfg[loop_ch].chn_id);
}
}
static void camera_stop_all(camera_ctx_t * ctx)
{
camera_ctx_t * cam_ctx = ctx;
int loop_ch;
for(loop_ch=0;loop_ch<cam_ctx->channel_num;loop_ch++)
{
csi_camera_channel_stop(cam_ctx->cam_handle, cam_ctx->chn_cfg[loop_ch].chn_id);
}
}
static camera_ctx_t * camera_open(camera_param_t *params)
{
int ret = 0;
char dev_name[128];
camera_ctx_t * cam_ctx = NULL;
int loop_ch;
LOG_O("Open Camera %d\n",params->video_id);
if(params==NULL || params->video_id <0)
{
LOG_E("param err\n");
return NULL;
}
if(params->channel_num> MAX_CHANNEL_NUM)
{
LOG_E("unsupoort channle num:%d \n",params->channel_num);
return NULL;
}
if(params->mode >=FRAME_INVALID)
{
LOG_E("unsupoort frame process mode:%d \n",params->mode);
return NULL;
}
cam_ctx = malloc(sizeof(camera_ctx_t));
if(!cam_ctx)
{
return NULL;
}
memset(cam_ctx,0x0,sizeof(camera_ctx_t));
// 打开Camera设备获取句柄作为后续操对象
sprintf(dev_name, "/dev/video%d", params->video_id);
if(csi_camera_open(&cam_ctx->cam_handle, dev_name))
{
LOG_E("Fail to open cam :%s\n",dev_name);
goto ONE_ERR;
}
for(loop_ch= CSI_CAMERA_CHANNEL_0;loop_ch<params->channel_num;loop_ch++)
{
cam_ctx->chn_cfg[loop_ch].chn_id = loop_ch;
cam_ctx->chn_cfg[loop_ch].img_fmt.pix_fmt = params->out_pic[loop_ch].fmt;
cam_ctx->chn_cfg[loop_ch].img_fmt.width= params->out_pic[loop_ch].width;
cam_ctx->chn_cfg[loop_ch].img_fmt.height = params->out_pic[loop_ch].height;
cam_ctx->chn_cfg[loop_ch].img_type = CSI_IMG_TYPE_DMA_BUF;
cam_ctx->chn_cfg[loop_ch].meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
if(csi_camera_channel_open(cam_ctx->cam_handle,&cam_ctx->chn_cfg[loop_ch]))
{
LOG_E("Fail to open cam %s,channel :%d\n",dev_name,loop_ch);
goto TWO_ERR;
}
if(params->mode == FRAME_SAVE_DISPLAY)
{
cam_ctx->disaply_plink[loop_ch] = vi_plink_create(&cam_ctx->chn_cfg[loop_ch]);
if(!cam_ctx->disaply_plink[loop_ch]&& loop_ch== CSI_CAMERA_CHANNEL_0) //temp only channel to display
{
LOG_E("Fail to create plink for cam %s,channel :%d\n",dev_name,loop_ch);
goto TWO_ERR;
}
}
cam_ctx->frame_mode[loop_ch]=params->mode;
cam_ctx->channel_num++;
}
if(csi_camera_create_event(&cam_ctx->event_handle,cam_ctx->cam_handle))
{
LOG_E("Fail to create event handler for cam %s\n",dev_name);
goto TWO_ERR;
}
cam_ctx->event_subscribe.type = CSI_CAMERA_EVENT_TYPE_CAMERA;
cam_ctx->event_subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
if(csi_camera_subscribe_event(cam_ctx->event_handle,&cam_ctx->event_subscribe))
{
LOG_E("Fail to subscribe eventfor cam %s\n",dev_name);
goto TWO_ERR;
}
for(loop_ch=0;loop_ch<cam_ctx->channel_num;loop_ch++)
{
cam_ctx->event_subscribe.type = CSI_CAMERA_EVENT_TYPE_CHANNEL0+loop_ch;
cam_ctx->event_subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY;
if(csi_camera_subscribe_event(cam_ctx->event_handle,&cam_ctx->event_subscribe))
{
LOG_E("Fail to subscribe eventfor cam %s\n",dev_name);
goto TWO_ERR;
}
}
LOG_O("%s open successfully\n",dev_name);
ret = pthread_create(&cam_ctx->cam_thread, NULL,
(void *)camera_event_thread, cam_ctx);
if (ret != 0) {
LOG_E("pthread_create() failed, ret=%d", ret);
goto TWO_ERR;
}
if(params->type == CAM_TYEP_IR)
{
cb_context[0].id=0;
cb_context[0].cam_handle = cam_ctx->cam_handle;
cb_context[0].dsp_id = 1;
cb_context[0].dsp_path = 3;
char test_set[16]="init";
cb_context[0].buf_size = 1920*1080;
cb_context[0].ref_buf=NULL;
csi_camera_dsp_algo_param_t algo_param_1={
.algo_name = "dsp1_dummy_algo_flo_1",
.algo_cb.cb = dsp_algo_result_cb,
.algo_cb.context = &cb_context[0],
.algo_cb.arg_size = sizeof(cb_args_t),
.sett_ptr = test_set,
.sett_size =sizeof(test_set),
.extra_buf_num =1,
.extra_buf_sizes = &cb_context[0].buf_size,
.extra_bufs = &cb_context[0].ref_buf,
};
if(csi_camera_set_dsp_algo_param(cam_ctx->cam_handle, cb_context[0].dsp_id,cb_context[0].dsp_path, &algo_param_1))
{
LOG_E("set DSP algo fail\n");
goto TWO_ERR;
}
cb_context[1].id=1;
cb_context[1].cam_handle = cam_ctx->cam_handle;
cb_context[1].dsp_id = 1;
cb_context[1].dsp_path = 4;
cb_context[1].buf_size = 1920*1080;
cb_context[1].ref_buf=NULL;
csi_camera_dsp_algo_param_t algo_param_2={
.algo_name = "dsp1_dummy_algo_flo",
.algo_cb.cb = dsp_algo_result_cb,
.algo_cb.context = &cb_context[1],
.algo_cb.arg_size = sizeof(cb_args_t),
.sett_ptr = test_set,
.sett_size =sizeof(test_set),
.extra_buf_num =1,
.extra_buf_sizes = &cb_context[1].buf_size,
.extra_bufs = &cb_context[1].ref_buf,
};
if(csi_camera_set_dsp_algo_param(cam_ctx->cam_handle, cb_context[1].dsp_id,cb_context[1].dsp_path, &algo_param_2))
{
LOG_E("set DSP algo fail\n");
goto TWO_ERR;
}
csi_camera_floodlight_led_set_flash_bright(cam_ctx->cam_handle, 500); //500ma
csi_camera_projection_led_set_flash_bright(cam_ctx->cam_handle, 500); //500ma
csi_camera_projection_led_set_mode(cam_ctx->cam_handle, LED_IR_ENABLE);
csi_camera_floodlight_led_set_mode(cam_ctx->cam_handle, LED_IR_ENABLE);
csi_camera_led_enable(cam_ctx->cam_handle, LED_FLOODLIGHT_PROJECTION);
}
// for(loop_ch=0;loop_ch<cam_ctx->channel_num;loop_ch++)
// {
// csi_camera_channel_start(cam_ctx->cam_handle, cam_ctx->chn_cfg[loop_ch].chn_id);
// }
get_system_time(__func__, __LINE__);
return cam_ctx;
TWO_ERR:
for(loop_ch=0;loop_ch<cam_ctx->channel_num;loop_ch++)
{
csi_camera_channel_close(cam_ctx->cam_handle, cam_ctx->chn_cfg[loop_ch].chn_id);
}
csi_camera_close(cam_ctx->cam_handle);
ONE_ERR:
free(cam_ctx);
return NULL;
}
static void camera_close(camera_ctx_t *ctx)
{
int loop_ch;
if(ctx->cam_handle==NULL)
{
return;
}
if (pthread_join(ctx->cam_thread, NULL)) {
LOG_E("pthread_join() failed\n");
}
csi_camera_unsubscribe_event(ctx->event_handle, &ctx->event_subscribe);
csi_camera_destory_event(ctx->event_handle);
// int loop_ch;
// for(loop_ch=0;loop_ch<ctx->channel_num;loop_ch++)
// {
// csi_camera_channel_stop(cam_ctx->cam_handle, cam_ctx->chn_cfg[loop_ch].chn_id);
// }
for(loop_ch=0;loop_ch<ctx->channel_num;loop_ch++)
{
csi_camera_channel_close(ctx->cam_handle, ctx->chn_cfg[loop_ch].chn_id);
}
csi_camera_close(ctx->cam_handle);
free(ctx);
}
int main(int argc, char *argv[])
{
char dev_name[128];
int camera_id = 0;
// 打印HAL接口版本号
csi_api_version_u version;
csi_camera_get_version(&version);
camera_param_t params[MAX_CAM_NUM];
camera_ctx_t * ctx[MAX_CAM_NUM]={NULL,NULL,NULL};
int cam_num=0;
bool running = false;
cam_num =parseParams(argc,argv,params);
if(cam_num <=0 || cam_num>MAX_CAM_NUM)
{
LOG_E("not camera is active\n");
exit(0);
}
for(int i =0;i<cam_num;i++)
{
switch(params[i].type)
{
case CAM_TYEP_RGB:
ctx[i]=camera_open(&params[i]);
break;
case CAM_TYEP_IR:
ctx[i]=camera_open(&params[i]);
break;
default:
LOG_E("unspuoort camera :%d\n",i);
continue;
}
if(ctx[i]==NULL)
{
LOG_E("camera_%d open %d fail\n",i,params[i].type);
goto ONR_ERR;
}
ctx[i]->cam_id = i;
ctx[i]->frame_num =0;
ctx[i]->exit = 0;
camera_start_all(ctx[i]);
running = true;
}
int all_exit;
do{
sleep(1);
all_exit = 1;
for(int i =0;i<cam_num;i++)
{
if(ctx[i]&&
ctx[i]->exit==0 &&
params[i].frames_to_stop>0 &&
ctx[i]->frame_num >=params[i].frames_to_stop)
{
camera_stop_all(ctx[i]);
ctx[i]->exit=1;
}
if(ctx[i])
all_exit &= ctx[i]->exit;
}
if(all_exit ==1)
{
LOG_O("all_exit\n");
running = false;
}
}while(running);
ONR_ERR:
for(int i =0;i<cam_num;i++)
{
if(ctx[i])
camera_close(ctx[i]);
}
exit(0);
}
static void dump_camera_meta(csi_frame_s *frame)
{
int i;
//printf("%s\n", __func__);
if (frame->meta.type != CSI_META_TYPE_CAMERA)
return;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
int meta_count = meta_data->count;
csi_camrea_meta_unit_s meta_unit;
csi_camera_frame_get_meta_unit(
&meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
LOG_I("meta_id=%d, meta_type=%d, meta_value=%d\n",
meta_unit.id, meta_unit.type, meta_unit.int_value);
}
static void dump_camera_frame(csi_frame_s *frame, csi_pixel_fmt_e fmt, int chan_id)
{
char file[128];
static int file_indx=0;
int size;
uint32_t indexd, j;
void *buf[3];
int buf_size;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
csi_camrea_meta_unit_s meta_unit;
csi_camera_frame_get_meta_unit(
&meta_unit, meta_data, CSI_CAMERA_META_ID_CAMERA_NAME);
sprintf(file,"demo_save_img%s_%d_%d",meta_unit.str_value,chan_id, file_indx++%10);
int fd = open(file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IROTH);
if(fd == -1) {
LOG_E("%s, %d, open file error!!!!!!!!!!!!!!!\n", __func__, __LINE__);
return ;
}
if (frame->img.type == CSI_IMG_TYPE_DMA_BUF) {
buf_size = frame->img.strides[0]*frame->img.height;
switch(fmt) {
case CSI_PIX_FMT_NV12:
case CSI_PIX_FMT_YUV_SEMIPLANAR_420:
if(frame->img.num_planes ==2)
{
buf_size+=frame->img.strides[1]*frame->img.height/2;
}
else{
LOG_O("img fomrat is not match with frame planes:%d\n",frame->img.num_planes);
return;
}
break;
case CSI_PIX_FMT_YUV_SEMIPLANAR_422:
if(frame->img.num_planes ==2)
{
buf_size+=frame->img.strides[1]*frame->img.height;
}
else{
LOG_O("img fomrat is not match with frame planes:%d\n",frame->img.num_planes);
return;
}
break;
default:
break;
}
buf[0]= mmap(0, buf_size, PROT_READ | PROT_WRITE,
MAP_SHARED, frame->img.dmabuf[0].fds, frame->img.dmabuf[0].offset);
// plane_size[1] = frame->img.strides[1]*frame->img.height;
// printf("frame plane 1 stride:%d,offset:%d\n", frame->img.strides[1],(uint32_t)frame->img.dmabuf[1].offset);
if(frame->img.num_planes ==2)
{
// buf[1] = mmap(0, plane_size[1]/2, PROT_READ | PROT_WRITE,
// MAP_SHARED, frame->img.dmabuf[1].fds, frame->img.dmabuf[1].offset);
buf[1] = buf[0]+frame->img.dmabuf[1].offset;
}
}
else{
buf[0] = frame->img.usr_addr[0];
buf[1] = frame->img.usr_addr[1];
}
LOG_O("%s,save img from : (%lx,%lx)size:%d to %s, fmt:%d width:%d stride:%d height:%d\n",__FUNCTION__, (uint64_t)buf[0],(uint64_t)buf[1],size, file, fmt, frame->img.width, frame->img.strides[0], frame->img.height);
if (frame->img.strides[0] == 0) {
frame->img.strides[0] = frame->img.width;
}
switch(fmt) {
case CSI_PIX_FMT_NV12:
case CSI_PIX_FMT_YUV_SEMIPLANAR_420:
for (j = 0; j < frame->img.height; j++) { //Y
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, frame->img.width);
}
for (j = 0; j < frame->img.height / 2; j++) { //UV
indexd = j*frame->img.strides[0];
write(fd, buf[1] + indexd, frame->img.width);
}
break;
case CSI_PIX_FMT_RGB_INTEVLEAVED_888:
case CSI_PIX_FMT_YUV_TEVLEAVED_444:
size = frame->img.width*3;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_BGR:
case CSI_PIX_FMT_RGB_PLANAR_888:
case CSI_PIX_FMT_YUV_PLANAR_444:
size = frame->img.width * frame->img.height * 3;
write(fd, buf[0], size);
break;
case CSI_PIX_FMT_RAW_8BIT:
size = frame->img.width;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_YUV_TEVLEAVED_422:
case CSI_PIX_FMT_RAW_10BIT:
case CSI_PIX_FMT_RAW_12BIT:
case CSI_PIX_FMT_RAW_14BIT:
case CSI_PIX_FMT_RAW_16BIT:
size = frame->img.width*2;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_YUV_SEMIPLANAR_422:
if (frame->img.strides[0] == 0) {
frame->img.strides[0] = frame->img.width;
}
for (j = 0; j < frame->img.height; j++) { //Y
indexd = j*frame->img.strides[0];
write(fd,buf[0] + indexd, frame->img.width);
}
for (j = 0; j < frame->img.height; j++) { //UV
indexd = j*frame->img.strides[0];
write(fd, buf[1]+ indexd, frame->img.width);
}
break;
default:
LOG_E("%s unsupported format to save\n", __func__);
exit(-1);
break;
}
close(fd);
munmap(buf[0],buf_size);
// munmap(buf[1],plane_size[1]);
LOG_O("%s exit\n", __func__);
}

View File

@@ -0,0 +1,710 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#define LOG_LEVEL 2
#define LOG_PREFIX "cam_demo_simple"
#include <syslog.h>
#include <csi_frame.h>
#include <csi_camera.h>
#include "csi_camera_dev_api.h"
// #include "vi_mem.h"
#ifdef PLATFORM_SIMULATOR
#include "apputilities.h"
#endif
static void dump_camera_meta(csi_frame_s *frame);
static void dump_camera_frame(csi_frame_s *frame, csi_pixel_fmt_e fmt);
#define TEST_DEVICE_NAME "/dev/video0"
#define CSI_CAMERA_TRUE 1
#define CSI_CAMERA_FALSE 0
typedef struct frame_fps {
uint64_t frameNumber;
struct timeval initTick;
float fps;
} frame_fps_t;
typedef struct cb_context{
int id;
csi_cam_handle_t cam_handle;
int dsp_id;
int dsp_path;
void *ref_buf;
int buf_size;
}cb_context_t;
typedef struct cb_args{
char setting[16];
uint32_t frame_id;
uint32_t timestap;
}cb_args_t;
cb_context_t cb_context[2];
void dsp_algo_result_cb(void*context,void*arg)
{
cb_context_t *ctx = (cb_context_t *)context;
cb_args_t *cb_args= (cb_args_t*)arg;
char update_setting[16];
uint32_t frame_id = cb_args->frame_id;
uint32_t frame_timestap = cb_args->timestap;
LOG_O("cb:%d,setting:%s,frame :%d,timestad:0x%x\n",ctx->id,cb_args->setting,frame_id,frame_timestap);
sprintf(update_setting, "update_%d", frame_id);
csi_camera_update_dsp_algo_setting(ctx->cam_handle,ctx->dsp_id,ctx->dsp_path,update_setting);
if(frame_id%20)
{
void *replace_buf;
csi_camera_update_dsp_algo_buf(ctx->cam_handle, ctx->dsp_id,ctx->dsp_path,ctx->ref_buf,&replace_buf);
LOG_O("cb:%d,old buffer:0x%lx,new buffer:0x%lx\n",ctx->id,(uint64_t)ctx->ref_buf,(uint64_t)replace_buf);
ctx->ref_buf = replace_buf;
}
}
static void usage(void)
{
printf(" 1 : video id cases\n");
printf(" 2 : channel cases\n");
printf(" 3 : dump enable\n");
printf(" 4 : display enable\n");
printf(" 5 : width\n");
printf(" 6 : heithg\n");
printf(" 7 : fmt\n");
printf(" 8 : frame_num\n");
printf(" 9 : file_id\n");
}
static void get_system_time(const char *func, int line_num)
{
struct timeval cur_time;
memset(&cur_time, 0, sizeof(cur_time));
gettimeofday(&cur_time, 0);
LOG_O("%s %s line_num = %d, cur_time.tv_sec = %ld, cur_time.tv_usec = %ld\n",
__func__, func, line_num, cur_time.tv_sec, cur_time.tv_usec);
}
int file_id = 0;
extern void *vi_plink_create(csi_camera_channel_cfg_s *chn_cfg);
extern void vi_plink_release(void * plink);
extern void display_camera_frame(void * plink, csi_frame_s *frame);
int main(int argc, char *argv[])
{
bool running = true;
int channel_id = -1;
int video_id = -1;
int dump_enable = -1;
int display_enable = -1;
int width = 0, height = 0, fmt = -1;
int ret = 0;
uint64_t frame_num = 0;
csi_camera_info_s camera_info;
memset(&camera_info, 0, sizeof(camera_info));
int chn_id = CSI_CAMERA_CHANNEL_0;
int env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL0;
frame_fps_t demo_fps;
memset(&demo_fps, 0, sizeof(demo_fps));
struct timeval init_time, cur_time;
memset(&init_time, 0, sizeof(init_time));
memset(&cur_time, 0, sizeof(cur_time));
get_system_time(__func__, __LINE__);
char dev_name[128];
// 打印HAL接口版本号
csi_api_version_u version;
csi_camera_get_version(&version);
if (argc == 5)
{
video_id = atoi(argv[1]);
channel_id = atoi(argv[2]);
dump_enable = atoi(argv[3]);
display_enable = atoi(argv[4]);
width = 640;
height = 480;
fmt = 1;
printf("%s, %s, %s, %s \n", argv[1],argv[2],argv[3],argv[4]);
printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$, %d, display_enable is %d\n", __LINE__, display_enable );
} else if (argc == 8) {
video_id = atoi(argv[1]);
channel_id = atoi(argv[2]);
dump_enable = atoi(argv[3]);
display_enable = atoi(argv[4]);
width = atoi(argv[5]);
height = atoi(argv[6]);
fmt = atoi(argv[7]);
}else if (argc == 9) {
video_id = atoi(argv[1]);
channel_id = atoi(argv[2]);
dump_enable = atoi(argv[3]);
display_enable = atoi(argv[4]);
width = atoi(argv[5]);
height = atoi(argv[6]);
fmt = atoi(argv[7]);
frame_num = atoi(argv[8]);
}else if (argc == 10) {
video_id = atoi(argv[1]);
channel_id = atoi(argv[2]);
dump_enable = atoi(argv[3]);
display_enable = atoi(argv[4]);
width = atoi(argv[5]);
height = atoi(argv[6]);
fmt = atoi(argv[7]);
frame_num = atoi(argv[8]);
file_id = atoi(argv[9]);
} else {
usage();
video_id = 0;
channel_id = 0;
dump_enable = 0;
display_enable = 0;
width = 640;
height = 480;
fmt = 1;
printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$, %d, display_enable is %d\n", __LINE__, display_enable );
}
sprintf(dev_name, "/dev/video%d", video_id);
LOG_O("Camera HAL version: %d.%d video_id = %d channel_id = %d size{%d, %d} fmt = %d\n", version.major, version.minor, video_id, channel_id, width, height, fmt);
// 获取设备中所有的Camera
struct csi_camera_infos camera_infos;
memset(&camera_infos, 0, sizeof(camera_infos));
csi_camera_query_list(&camera_infos);
// 打印所有设备所支持的Camera
for (int i = 0; i < camera_infos.count; i++) {
camera_info = camera_infos.info[i];
printf("Camera[%d]: camera_name='%s', device_name='%s', bus_info='%s', capabilities=0x%08x\n",
i,
camera_info.camera_name, camera_info.device_name, camera_info.bus_info,
camera_info.capabilities);
printf("Camera[%d] caps are:\n", i); /* The caps are: Video capture, metadata capture */
for (int j = 1; j <= 0x08000000; j = j << 1) {
switch (camera_info.capabilities & j) {
case CSI_CAMERA_CAP_VIDEO_CAPTURE:
printf("\t camera_infos.info[%d]:Video capture,\n", i);
break;
case CSI_CAMERA_CAP_META_CAPTURE:
printf("\t camera_infos.info[%d] metadata capture,\n", i);
break;
default:
if (camera_info.capabilities & j) {
printf("\t camera_infos.info[%d] unknown capabilities(0x%08x)\n", i,
camera_info.capabilities & j);
}
break;
}
}
}
/* Camera[0]: camera_name='RGB_Camera', device_name='/dev/video0', bus_info='CSI-MIPI', capabilities=0x00800001
* Camera[1]: camera_name:'Mono_Camera', device_name:'/dev/video8', bus_info='USB', capabilities=0x00000001
*/
bool found_camera = false;
for (int i = 0; i < camera_infos.count; i++) {
if (strcmp(camera_infos.info[i].device_name, dev_name) == 0) {
camera_info = camera_infos.info[i];
printf("found device_name:'%s'\n", camera_info.device_name);
found_camera = true;
break;
}
}
if (!found_camera) {
LOG_E("Can't find camera_name:'%s'\n", dev_name);
exit(-1);
}
get_system_time(__func__, __LINE__);
// 打开Camera设备获取句柄作为后续操对象
csi_cam_handle_t cam_handle;
csi_camera_open(&cam_handle, camera_info.device_name);
get_system_time(__func__, __LINE__);
// 获取Camera支持的工作模式
struct csi_camera_modes camera_modes;
csi_camera_get_modes(cam_handle, &camera_modes);
// 打印camera所支持的所有工作模式
printf("Camera:'%s' modes are:\n", dev_name);
printf("{\n");
for (int i = 0; i < camera_modes.count; i++) {
printf("\t mode_id=%d: description:'%s'\n",
camera_modes.modes[i].mode_id, camera_modes.modes[i].description);
}
printf("}\n");
// 设置camera的工作模式及其配置
csi_camera_mode_cfg_s camera_cfg;
camera_cfg.mode_id = 1;
camera_cfg.calibriation = NULL; // 采用系统默认配置
camera_cfg.lib3a = NULL; // 采用系统默认配置
csi_camera_set_mode(cam_handle, &camera_cfg);
// 获取单个可控单元的属性
csi_camera_property_description_s description;
/* id=0x0098090x, type=2 default=0 value=1 */
/* Other example:
* id=0x0098090y, type=3 min=0 max=255 step=1 default=127 value=116
* id=0x0098090z, type=4 min=0 max=3 default=0 value=2
* 0: IDLE
* 1: BUSY
* 2: REACHED
* 3: FAILED
*/
// 轮询获取所有可控制的单元
printf("all properties are:\n");
description.id = CSI_CAMERA_PID_HFLIP;
while (!csi_camera_query_property(cam_handle, &description)) {
switch (description.type) {
case (CSI_CAMERA_PROPERTY_TYPE_INTEGER):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.int_value, description.value.int_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BOOLEAN):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.bool_value, description.value.bool_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_ENUM):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.enum_value, description.value.enum_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_STRING):
printf("id=0x%08x type=%d default=%s value=%s\n",
description.id, description.type,
description.default_value.str_value, description.value.str_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BITMASK):
printf("id=0x%08x type=%d default=%x value=%x\n",
description.id, description.type,
description.default_value.bitmask_value, description.value.bitmask_value);
break;
default:
LOG_E("error type!\n");
break;
}
description.id |= CSI_CAMERA_FLAG_NEXT_CTRL;
}
// 同时配置多个参数
csi_camera_properties_s properties;
csi_camera_property_s property[3];
property[0].id = CSI_CAMERA_PID_HFLIP;
property[0].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
property[0].value.bool_value = false;
property[1].id = CSI_CAMERA_PID_VFLIP;
property[1].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
property[1].value.bool_value = false;
property[2].id = CSI_CAMERA_PID_ROTATE;
property[2].type = CSI_CAMERA_PROPERTY_TYPE_INTEGER;
property[2].value.int_value = 0;
properties.count = 3;
properties.property = property;
if (csi_camera_set_property(cam_handle, &properties) < 0) {
LOG_O("set_property fail!\n");
}
LOG_O("set_property ok!\n");
// extern int csi_camera_set_pp_path_param(csi_cam_handle_t cam_handle, uint16_t line_num,uint16_t buf_mode);
// csi_camera_set_pp_path_param(cam_handle,80,0);
// 查询输出channel
switch (channel_id) {
case 0:
chn_id = CSI_CAMERA_CHANNEL_0;
env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL0;
break;
case 1:
chn_id = CSI_CAMERA_CHANNEL_1;
env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL1;
break;
case 2:
chn_id = CSI_CAMERA_CHANNEL_2;
env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL2;
break;
case 3:
chn_id = CSI_CAMERA_CHANNEL_3;
env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL3;
break;
case 4:
chn_id = CSI_CAMERA_CHANNEL_4;
env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL4;
break;
case 5:
chn_id = CSI_CAMERA_CHANNEL_5;
env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL5;
break;
case 6:
chn_id = CSI_CAMERA_CHANNEL_6;
env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL6;
break;
case 7:
chn_id = CSI_CAMERA_CHANNEL_7;
env_type = CSI_CAMERA_EVENT_TYPE_CHANNEL7;
break;
default:
LOG_E("fail to check chn_id = %d unsupport\n", chn_id);
exit(-1);
}
csi_camera_channel_cfg_s chn_cfg;
chn_cfg.chn_id = chn_id;
csi_camera_channel_query(cam_handle, &chn_cfg);
if (chn_cfg.status != CSI_CAMERA_CHANNEL_CLOSED) {
LOG_E("Can't open chn_id = %d\n", chn_id);
exit(-1);
}
extern int csi_camera_set_pp_path_param(csi_cam_handle_t cam_handle, uint16_t line_num,uint16_t buf_mode);
/*set PP line num to default and enable sram*/
csi_camera_set_pp_path_param(cam_handle,0,1);
// 打开输出channel
chn_cfg.chn_id = chn_id;
chn_cfg.frm_cnt = 1;
chn_cfg.img_fmt.width = width;
chn_cfg.img_fmt.height = height;
chn_cfg.img_fmt.pix_fmt = fmt;
chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
CSI_CAMERA_CHANNEL_CAPTURE_META;
ret = csi_camera_channel_open(cam_handle, &chn_cfg);
if (ret) {
exit(-1);
}
get_system_time(__func__, __LINE__);
/*init for vi->vo plink*/
void * display_plink = NULL;
if (display_enable == 1) {
chn_cfg.chn_id = chn_id;
display_plink = vi_plink_create(&chn_cfg);
if(display_plink==NULL)
{
LOG_E("plink create fail\n");
exit(-1);
}
}
// 订阅Event
csi_cam_event_handle_t event_handle;
csi_camera_create_event(&event_handle, cam_handle);
csi_camera_event_subscription_s subscribe;
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
csi_camera_subscribe_event(event_handle, &subscribe);
subscribe.type =
env_type; // 订阅Channel0的FRAME_READY事件
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
csi_camera_subscribe_event(event_handle, &subscribe);
/* for dsp algo setting
cb_context[0].id=0;
cb_context[0].cam_handle = cam_handle;
cb_context[0].dsp_id = 1;
cb_context[0].dsp_path = 2;
char test_set[16]="init";
cb_context[0].buf_size = 1920*1080;
cb_context[0].ref_buf=NULL;
csi_camera_dsp_algo_param_t algo_param_1={
.algo_name = "dsp1_dummy_algo_flo",
.algo_cb.cb = dsp_algo_result_cb,
.algo_cb.context = &cb_context[0],
.algo_cb.arg_size = sizeof(cb_args_t),
.sett_ptr = test_set,
.sett_size =16,
.extra_buf_num =1,
.extra_buf_sizes = &cb_context[0].buf_size,
.extra_bufs = &cb_context[0].ref_buf,
};
if(csi_camera_set_dsp_algo_param(cam_handle,cb_context[0].dsp_id,cb_context[0].dsp_path, &algo_param_1))
{
LOG_E("set DSP algo fail\n");
}
*/
// 开始从channel中取出准备好的frame
csi_camera_channel_start(cam_handle, chn_id);
get_system_time(__func__, __LINE__);
// 处理订阅的Event
csi_frame_s frame;
struct csi_camera_event event;
while (running) {
if (frame_num != 0) {
if (demo_fps.frameNumber > frame_num) {
running = false;
}
}
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
csi_camera_get_event(event_handle, &event, timeout);
// printf("%s event.type = %d, event.id = %d\n", __func__, event.type, event.id);
switch (event.type) {
case CSI_CAMERA_EVENT_TYPE_CAMERA:
switch (event.id) {
case CSI_CAMERA_EVENT_ERROR:
// do sth.
LOG_O("get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!\n");
break;
case CSI_CAMERA_EVENT_WARNING:
LOG_O("get CAMERA EVENT CSI_CAMERA_EVENT_WRN,RC: %s\n",event.bin);
break;
default:
break;
}
break;
case CSI_CAMERA_EVENT_TYPE_CHANNEL0:
case CSI_CAMERA_EVENT_TYPE_CHANNEL1:
case CSI_CAMERA_EVENT_TYPE_CHANNEL2:
case CSI_CAMERA_EVENT_TYPE_CHANNEL3:
case CSI_CAMERA_EVENT_TYPE_CHANNEL4:
case CSI_CAMERA_EVENT_TYPE_CHANNEL5:
case CSI_CAMERA_EVENT_TYPE_CHANNEL6:
case CSI_CAMERA_EVENT_TYPE_CHANNEL7:
switch (event.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
get_system_time(__func__, __LINE__);
int read_frame_count = csi_camera_get_frame_count(cam_handle,
chn_id);
unsigned long diff;
if (init_time.tv_usec == 0)
gettimeofday(&init_time,0);//osGetTick();
gettimeofday(&cur_time, 0);
diff = 1000000 * (cur_time.tv_sec-init_time.tv_sec)+ cur_time.tv_usec-init_time.tv_usec;
demo_fps.frameNumber++;
if (diff != 0)
demo_fps.fps = (float)demo_fps.frameNumber / diff * 1000000.0f;
LOG_O("%s %d read_frame_count = %d, frame_count = %ld, fps = %.2f diff = %ld\n", __func__, __LINE__, read_frame_count, demo_fps.frameNumber, demo_fps.fps, diff);
for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(cam_handle, chn_id, &frame, timeout);
#ifdef PLATFORM_SIMULATOR
if (frame.img.type == CSI_IMG_TYPE_DMA_BUF) {
void *phyaddr = vi_mem_import(frame.img.dmabuf[0].fds);
void *p = vi_mem_map(phyaddr) + frame.img.dmabuf[0].offset;
show_frame_image(p, frame.img.height, frame.img.width);
vi_mem_release(phyaddr);
} else {
show_frame_image(frame.img.usr_addr[0], frame.img.height, frame.img.width);
}
#endif
// printf("main 443 phyaddr=%p\n", vi_mem_import(frame.img.dmabuf[0].fds));
dump_camera_meta(&frame);
chn_cfg.chn_id = chn_id;
csi_camera_channel_query(cam_handle, &chn_cfg);
frame.img.pix_format = chn_cfg.img_fmt.pix_fmt;
if (dump_enable) {
dump_camera_frame(&frame, chn_cfg.img_fmt.pix_fmt);
}
if (display_enable == 1) {
display_camera_frame(display_plink, &frame);
}
// csi_camera_frame_unlock(cam_handle, &frame);
csi_camera_put_frame(&frame);
csi_frame_release(&frame);
}
break;
}
default:
break;
}
break;
default:
break;
}
}
csi_camera_channel_stop(cam_handle, chn_id);
usleep (1000000);
// 取消订阅某一个event, 也可以直接调用csi_camera_destory_event结束所有的订阅
subscribe.type = env_type;
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY;
csi_camera_unsubscribe_event(event_handle, &subscribe);
csi_camera_destory_event(event_handle);
csi_camera_channel_close(cam_handle, chn_id);
csi_camera_close(cam_handle);
if(display_plink)
{
vi_plink_release(display_plink);
}
}
static void dump_camera_meta(csi_frame_s *frame)
{
int i;
if (frame->meta.type != CSI_META_TYPE_CAMERA)
return;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
int meta_count = meta_data->count;
csi_camrea_meta_unit_s meta_unit;
csi_camera_frame_get_meta_unit(
&meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
LOG_O("meta_id=%d, meta_type=%d, meta_value=%d\n",
meta_unit.id, meta_unit.type, meta_unit.int_value);
}
static void dump_camera_frame(csi_frame_s *frame, csi_pixel_fmt_e fmt)
{
char file[128];
static int file_indx=0;
int size;
uint32_t indexd, j;
void *buf[3];
int buf_size;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
csi_camrea_meta_unit_s meta_unit;
csi_camera_frame_get_meta_unit(
&meta_unit, meta_data, CSI_CAMERA_META_ID_CAMERA_NAME);
sprintf(file,"demo_save_img%s_%d_%d",meta_unit.str_value,file_id, file_indx++%10);
int fd = open(file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IROTH);
if(fd == -1) {
LOG_E("%s, %d, open file error!!!!!!!!!!!!!!!\n", __func__, __LINE__);
return ;
}
if (frame->img.type == CSI_IMG_TYPE_DMA_BUF) {
buf_size = frame->img.strides[0]*frame->img.height;
switch(fmt) {
case CSI_PIX_FMT_NV12:
case CSI_PIX_FMT_YUV_SEMIPLANAR_420:
if(frame->img.num_planes ==2)
{
buf_size+=frame->img.strides[1]*frame->img.height/2;
}
else{
LOG_E("img fomrat is not match with frame planes:%d\n",frame->img.num_planes);
return;
}
break;
case CSI_PIX_FMT_YUV_SEMIPLANAR_422:
if(frame->img.num_planes ==2)
{
buf_size+=frame->img.strides[1]*frame->img.height;
}
else{
LOG_E("img fomrat is not match with frame planes:%d\n",frame->img.num_planes);
return;
}
break;
default:
break;
}
buf[0]= mmap(0, buf_size, PROT_READ | PROT_WRITE,
MAP_SHARED, frame->img.dmabuf[0].fds, frame->img.dmabuf[0].offset);
// plane_size[1] = frame->img.strides[1]*frame->img.height;
// printf("frame plane 1 stride:%d,offset:%d\n", frame->img.strides[1],(uint32_t)frame->img.dmabuf[1].offset);
if(frame->img.num_planes ==2)
{
// buf[1] = mmap(0, plane_size[1]/2, PROT_READ | PROT_WRITE,
// MAP_SHARED, frame->img.dmabuf[1].fds, frame->img.dmabuf[1].offset);
buf[1] = buf[0]+frame->img.dmabuf[1].offset;
}
}
else{
buf[0] = frame->img.usr_addr[0];
buf[1] = frame->img.usr_addr[1];
}
LOG_O("%s,save img from : (%lx,%lx)size:%d to %s, fmt:%d width:%d stride:%d height:%d\n",__FUNCTION__, (uint64_t)buf[0],(uint64_t)buf[1],size, file, fmt, frame->img.width, frame->img.strides[0], frame->img.height);
if (frame->img.strides[0] == 0) {
frame->img.strides[0] = frame->img.width;
}
switch(fmt) {
case CSI_PIX_FMT_NV12:
case CSI_PIX_FMT_YUV_SEMIPLANAR_420:
for (j = 0; j < frame->img.height; j++) { //Y
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, frame->img.width);
}
for (j = 0; j < frame->img.height / 2; j++) { //UV
indexd = j*frame->img.strides[0];
write(fd, buf[1] + indexd, frame->img.width);
}
break;
case CSI_PIX_FMT_RGB_INTEVLEAVED_888:
case CSI_PIX_FMT_YUV_TEVLEAVED_444:
size = frame->img.width*3;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_BGR:
case CSI_PIX_FMT_RGB_PLANAR_888:
case CSI_PIX_FMT_YUV_PLANAR_444:
size = frame->img.width * frame->img.height * 3;
write(fd, buf[0], size);
break;
case CSI_PIX_FMT_RAW_8BIT:
size = frame->img.width;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_YUV_TEVLEAVED_422:
case CSI_PIX_FMT_RAW_10BIT:
case CSI_PIX_FMT_RAW_12BIT:
case CSI_PIX_FMT_RAW_14BIT:
case CSI_PIX_FMT_RAW_16BIT:
size = frame->img.width*2;
for (j = 0; j < frame->img.height; j++) {
indexd = j*frame->img.strides[0];
write(fd, buf[0] + indexd, size);
}
break;
case CSI_PIX_FMT_YUV_SEMIPLANAR_422:
if (frame->img.strides[0] == 0) {
frame->img.strides[0] = frame->img.width;
}
for (j = 0; j < frame->img.height; j++) { //Y
indexd = j*frame->img.strides[0];
write(fd,buf[0] + indexd, frame->img.width);
}
for (j = 0; j < frame->img.height; j++) { //UV
indexd = j*frame->img.strides[0];
write(fd, buf[1]+ indexd, frame->img.width);
}
break;
default:
LOG_E("%s unsupported format to save\n", __func__);
exit(-1);
break;
}
close(fd);
munmap(buf[0],buf_size);
// munmap(buf[1],plane_size[1]);
LOG_O("%s exit\n", __func__);
}

View File

@@ -0,0 +1,303 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "camera_demo1"
#include <syslog.h>
#include <csi_frame.h>
#include <csi_camera.h>
#ifdef PLATFORM_SIMULATOR
#include "apputilities.h"
#include "platform_action.h"
#endif
static void dump_camera_meta(csi_frame_s *frame);
//#define TEST_DEVICE_NAME "/dev/fake"
#define TEST_DEVICE_NAME "/dev/video0"
int main(int argc, char *argv[])
{
bool running = true;
csi_camera_info_s camera_info;
// 打印HAL接口版本号
csi_api_version_u version;
csi_camera_get_version(&version);
printf("Camera HAL version: %d.%d\n", version.major, version.minor);
// 获取设备中所有的Camera
struct csi_camera_infos camera_infos;
csi_camera_query_list(&camera_infos);
// 打印所有设备所支持的Camera
for (int i = 0; i < camera_infos.count; i++) {
camera_info = camera_infos.info[i];
printf("Camera[%d]: camera_name='%s', device_name='%s', bus_info='%s', capabilities=0x%08x\n",
i,
camera_info.camera_name, camera_info.device_name, camera_info.bus_info,
camera_info.capabilities);
printf("Camera[%d] caps are:\n",
i); /* The caps are: Video capture, metadata capture */
for (int j = 1; j <= 0x08000000; j = j << 1) {
switch (camera_info.capabilities & j) {
case CSI_CAMERA_CAP_VIDEO_CAPTURE:
printf("\t camera_infos.info[%d]:Video capture,\n", i);
break;
case CSI_CAMERA_CAP_META_CAPTURE:
printf("\t camera_infos.info[%d] metadata capture,\n", i);
break;
default:
if (camera_info.capabilities & j) {
printf("\t camera_infos.info[%d] unknown capabilities(0x%08x)\n", i,
camera_info.capabilities & j);
}
break;
}
}
}
/* Camera[0]: camera_name='RGB_Camera', device_name='/dev/video0', bus_info='CSI-MIPI', capabilities=0x00800001
* Camera[1]: camera_name:'Mono_Camera', device_name:'/dev/video8', bus_info='USB', capabilities=0x00000001
*/
bool found_camera = false;
for (int i = 0; i < camera_infos.count; i++) {
if (strcmp(camera_infos.info[i].device_name, TEST_DEVICE_NAME) == 0) {
camera_info = camera_infos.info[i];
printf("found device_name:'%s'\n", camera_info.device_name);
found_camera = true;
break;
}
}
if (!found_camera) {
LOG_E("Can't find camera_name:'%s'\n", TEST_DEVICE_NAME);
exit(-1);
}
// 打开Camera设备获取句柄作为后续操对象
csi_cam_handle_t cam_handle;
csi_camera_open(&cam_handle, camera_info.device_name);
// 获取Camera支持的工作模式
struct csi_camera_modes camera_modes;
csi_camera_get_modes(cam_handle, &camera_modes);
// 打印camera所支持的所有工作模式
printf("Camera:'%s' modes are:\n", TEST_DEVICE_NAME);
printf("{\n");
for (int i = 0; i < camera_modes.count; i++) {
printf("\t mode_id=%d: description:'%s'\n",
camera_modes.modes[i].mode_id, camera_modes.modes[i].description);
}
printf("}\n");
// 设置camera的工作模式及其配置
csi_camera_mode_cfg_s camera_cfg;
camera_cfg.mode_id = 1;
camera_cfg.calibriation = NULL; // 采用系统默认配置
camera_cfg.lib3a = NULL; // 采用系统默认配置
csi_camera_set_mode(cam_handle, &camera_cfg);
// 获取单个可控单元的属性
csi_camera_property_description_s description;
description.id = CSI_CAMERA_PID_HFLIP;
csi_camera_query_property(cam_handle, &description);
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.bool_value, description.value.bool_value);
/* id=0x0098090x, type=2 default=0 value=1 */
/* Other example:
* id=0x0098090y, type=3 min=0 max=255 step=1 default=127 value=116
* id=0x0098090z, type=4 min=0 max=3 default=0 value=2
* 0: IDLE
* 1: BUSY
* 2: REACHED
* 3: FAILED
*/
// 轮询获取所有可控制的单元
printf("all properties are:\n");
description.id = CSI_CAMERA_PID_HFLIP;
while (!csi_camera_query_property(cam_handle, &description)) {
switch (description.type) {
case (CSI_CAMERA_PROPERTY_TYPE_INTEGER):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.int_value, description.value.int_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BOOLEAN):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.bool_value, description.value.bool_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_ENUM):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.enum_value, description.value.enum_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_STRING):
printf("id=0x%08x type=%d default=%s value=%s\n",
description.id, description.type,
description.default_value.str_value, description.value.str_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BITMASK):
printf("id=0x%08x type=%d default=%x value=%x\n",
description.id, description.type,
description.default_value.bitmask_value, description.value.bitmask_value);
break;
default:
LOG_E("error type!\n");
break;
}
description.id |= CSI_CAMERA_FLAG_NEXT_CTRL;
}
// 同时配置多个参数
csi_camera_properties_s properties;
csi_camera_property_s property[2];
property[0].id = CSI_CAMERA_PID_HFLIP;
property[0].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
property[0].value.bool_value = true;
property[1].id = CSI_CAMERA_PID_VFLIP;
property[1].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
property[1].value.bool_value = false;
properties.count = 2;
properties.property = property;
csi_camera_set_property(cam_handle, &properties);
LOG_O("set_property ok!\n");
csi_camera_get_property(cam_handle, &properties);
// 查询输出channel
csi_camera_channel_cfg_s chn_cfg;
chn_cfg.chn_id = CSI_CAMERA_CHANNEL_0;
csi_camera_channel_query(cam_handle, &chn_cfg);
if (chn_cfg.status != CSI_CAMERA_CHANNEL_CLOSED) {
printf("Can't open CSI_CAMERA_CHANNEL_0\n");
exit(-1);
}
// 打开输出channel
chn_cfg.chn_id = CSI_CAMERA_CHANNEL_0;
chn_cfg.frm_cnt = 4;
chn_cfg.img_fmt.width = 1280;
chn_cfg.img_fmt.height = 720;
chn_cfg.img_fmt.pix_fmt = CSI_PIX_FMT_BGR;
chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
CSI_CAMERA_CHANNEL_CAPTURE_META;
csi_camera_channel_open(cam_handle, &chn_cfg);
// 订阅Event
csi_cam_event_handle_t event_handle;
csi_camera_create_event(&event_handle, cam_handle);
csi_camera_event_subscription_s subscribe;
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
csi_camera_subscribe_event(event_handle, &subscribe);
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CHANNEL0; // 订阅Channel0的FRAME_READY事件
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
csi_camera_subscribe_event(event_handle, &subscribe);
// 开始从channel中取出准备好的frame
csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_0);
// 处理订阅的Event
csi_frame_s frame;
struct csi_camera_event event;
while (running) {
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
csi_camera_get_event(event_handle, &event, timeout);
switch (event.type) {
case CSI_CAMERA_EVENT_TYPE_CAMERA:
switch (event.id) {
case CSI_CAMERA_EVENT_ERROR:
// do sth.
LOG_D("get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!\n");
break;
default:
break;
}
case CSI_CAMERA_EVENT_TYPE_CHANNEL0:
switch (event.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
int read_frame_count = csi_camera_get_frame_count(cam_handle,
CSI_CAMERA_CHANNEL_0);
for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(cam_handle, CSI_CAMERA_CHANNEL_0, &frame, timeout);
// frame.image: {.width, .height, .pix_fmt, .dma-buf}
//show_frame_image(frame.image); // 伪代码
#ifdef PLATFORM_SIMULATOR
camera_action_image_display(&frame);
csi_camera_put_frame(&frame);
#endif
// frame.meta: {.count,
// .meta_data[]={meta_id, type,
// union{int_value, str_value, ...}}}
dump_camera_meta(&frame);
//csi_camera_put_frame(&frame);
}
break;
}
default:
break;
}
default:
break;
}
}
// 取消订阅某一个event, 也可以直接调用csi_camera_destory_event结束所有的订阅
subscribe.type = CSI_CAMERA_EVENT_TYPE_CHANNEL0;
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY;
csi_camera_unsubscribe_event(event_handle, &subscribe);
csi_camera_destory_event(event_handle);
csi_camera_channel_stop(cam_handle, CSI_CAMERA_CHANNEL_0);
csi_camera_channel_close(cam_handle, CSI_CAMERA_CHANNEL_0);
csi_camera_close(cam_handle);
}
static void dump_camera_meta(csi_frame_s *frame)
{
int i;
if (frame->meta.type != CSI_META_TYPE_CAMERA)
return;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
int meta_count = meta_data->count;
csi_camrea_meta_unit_s meta_unit;
for (i = 0; i < meta_count; i++) {
csi_camera_frame_get_meta_unit(
&meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
printf("meta_id=%d, meta_type=%d, meta_value=%d",
meta_unit.id, meta_unit.type, meta_unit.int_value);
}
}

View File

@@ -0,0 +1,357 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LOG_LEVEL 2
#define LOG_PREFIX "camera_demo2"
#include <syslog.h>
#include <csi_frame.h>
#include <csi_camera.h>
#ifdef PLATFORM_SIMULATOR
#include "apputilities.h"
#include "platform_action.h"
#endif
static void dump_camera_meta(csi_frame_s *frame);
#define TEST_DEVICE_NAME "/dev/video0"
int main(int argc, char *argv[])
{
uint32_t i;
bool running = true;
csi_camera_info_s camera_info;
// 获取设备中所有的Camera
struct csi_camera_infos camera_infos;
csi_camera_query_list(&camera_infos);
LOG_O("csi_camera_query_list() OK\n");
// 打印所有设备所支持的Camera
for (i = 0; i < camera_infos.count; i++) {
printf("Camera[%d]: camera_name='%s', device_name='%s', bus_info='%s', capabilities=0x%08x\n",
i, camera_infos.info[i].camera_name, camera_infos.info[i].device_name,
camera_infos.info[i].bus_info, camera_infos.info[i].capabilities);
}
/* Camera[0]: camera_name='RGB_Camera', device_name='/dev/video0', bus_info='CSI-MIPI', capabilities=0x00800001
* Camera[1]: camera_name:'Mono_Camera', device_name:'/dev/video8', bus_info='USB', capabilities=0x00000001
*/
bool found_camera = false;
for (i = 0; i < camera_infos.count; i++) {
if (strcmp(camera_infos.info[i].device_name, TEST_DEVICE_NAME) == 0) {
camera_info = camera_infos.info[i];
printf("found device_name:'%s'\n", camera_info.device_name);
found_camera = true;
break;
}
}
if (!found_camera) {
LOG_E("Can't find camera_name:'%s'\n", TEST_DEVICE_NAME);
exit(-1);
}
printf("The caps are:\n");
for (i = 1; i < 0x80000000; i = i << 1) {
switch (camera_info.capabilities & i) {
case CSI_CAMERA_CAP_VIDEO_CAPTURE:
printf("\t Video capture\n");
break;
case CSI_CAMERA_CAP_META_CAPTURE:
printf("\t metadata capture\n");
break;
default:
if (camera_info.capabilities & i) {
printf("\t unknown capabilities(0x%08x)\n", camera_info.capabilities & i);
}
break;
}
}
/* The caps are: Video capture, metadata capture */
// 打开Camera设备获取句柄作为后续操对象
csi_cam_handle_t cam_handle;
csi_camera_open(&cam_handle, camera_info.device_name);
LOG_O("csi_camera_open() OK\n");
// 获取Camera支持的工作模式
struct csi_camera_modes camera_modes;
camera_modes.count = 0;
csi_camera_get_modes(cam_handle, &camera_modes);
LOG_O("csi_camera_get_modes() OK\n");
// 打印camera所支持的所有工作模式
printf(" Camera:'%s' modes are:{\n", TEST_DEVICE_NAME);
for (i = 0; i < camera_modes.count; i++) {
printf("\t mode_id=%d: description:'%s'\n",
camera_modes.modes[i].mode_id, camera_modes.modes[i].description);
}
printf("}\n");
// 设置camera的工作模式及其配置
csi_camera_mode_cfg_s camera_cfg;
camera_cfg.mode_id = 1;
camera_cfg.calibriation = NULL; // 采用系统默认配置
camera_cfg.lib3a = NULL; // 采用系统默认配置
csi_camera_set_mode(cam_handle, &camera_cfg);
// 获取单个可控单元的属性
csi_camera_property_description_s description;
description.id = CSI_CAMERA_PID_HFLIP;
csi_camera_query_property(cam_handle, &description);
printf("properity id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.bool_value, description.value.bool_value);
/* id=0x0098090x, type=2 default=0 value=1 */
/* Other example:
* id=0x0098090y, type=3 min=0 max=255 step=1 default=127 value=116
* id=0x0098090z, type=4 min=0 max=3 default=0 value=2
* 0: IDLE
* 1: BUSY
* 2: REACHED
* 3: FAILED
*/
// 轮询获取所有可控制的单元
description.id = CSI_CAMERA_FLAG_NEXT_CTRL;
while (!csi_camera_query_property(cam_handle, &description)) {
//printf(...); // 打印属性
switch (description.type) {
case (CSI_CAMERA_PROPERTY_TYPE_INTEGER):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.int_value, description.value.int_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BOOLEAN):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.bool_value, description.value.bool_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_ENUM):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.enum_value, description.value.enum_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_STRING):
printf("id=0x%08x type=%d default=%s value=%s\n",
description.id, description.type,
description.default_value.str_value, description.value.str_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BITMASK):
printf("id=0x%08x type=%d default=%x value=%x\n",
description.id, description.type,
description.default_value.bitmask_value, description.value.bitmask_value);
break;
default:
LOG_E("error type!\n");
break;
}
description.id |= CSI_CAMERA_FLAG_NEXT_CTRL;
}
LOG_O("csi_camera_query_property() OK\n");
// 同时配置多个参数
csi_camera_properties_s properties;
csi_camera_property_s property[2];
property[0].id = CSI_CAMERA_PID_EXPOSURE_MODE;
property[0].type = CSI_CAMERA_PROPERTY_TYPE_ENUM;
property[0].value.enum_value = CSI_CAMERA_EXPOSURE_MODE_AUTO;
property[1].id = CSI_CAMERA_PID_EXPOSURE_MODE;
property[1].type = CSI_CAMERA_PROPERTY_TYPE_ENUM;
property[1].value.enum_value = CSI_CAMERA_EXPOSURE_MANUAL;
properties.count = 2;
properties.property = property;
csi_camera_get_property(cam_handle, &properties);
LOG_O("csi_camera_get_property() OK\n");
// 查询输出channel
csi_camera_channel_cfg_s chn_cfg;
chn_cfg.chn_id = CSI_CAMERA_CHANNEL_0;
csi_camera_channel_query(cam_handle, &chn_cfg);
if (chn_cfg.status != CSI_CAMERA_CHANNEL_CLOSED) {
printf("Can't open CSI_CAMERA_CHANNEL_0\n");
exit(-1);
}
LOG_O("csi_camera_channel_query() OK\n");
// 打开输出channel_0
chn_cfg.chn_id = CSI_CAMERA_CHANNEL_0;
chn_cfg.frm_cnt = 4;
chn_cfg.img_fmt.width = 640;
chn_cfg.img_fmt.height = 480;
chn_cfg.img_fmt.pix_fmt = CSI_PIX_FMT_I420;
chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
CSI_CAMERA_CHANNEL_CAPTURE_META;
csi_camera_channel_open(cam_handle, &chn_cfg);
LOG_O("CSI_CAMERA_CHANNEL_0: csi_camera_channel_open() OK\n");
// 打开输出channel_1
chn_cfg.chn_id = CSI_CAMERA_CHANNEL_1;
chn_cfg.frm_cnt = 4;
chn_cfg.img_fmt.width = 1280;
chn_cfg.img_fmt.height = 720;
chn_cfg.img_fmt.pix_fmt = CSI_PIX_FMT_BGR;
chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
CSI_CAMERA_CHANNEL_CAPTURE_META;
csi_camera_channel_open(cam_handle, &chn_cfg);
LOG_O("CSI_CAMERA_CHANNEL_1: csi_camera_channel_open() OK\n");
// 订阅Event
csi_cam_event_handle_t event_handle;
csi_camera_create_event(&event_handle, cam_handle);
struct csi_camera_event_subscription subscribe;
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
csi_camera_subscribe_event(event_handle, &subscribe);
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CHANNEL0; // 订阅Channel0的FRAME_READY事件
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
csi_camera_subscribe_event(event_handle, &subscribe);
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CHANNEL1; // 订阅Channel0的FRAME_READY事件
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
csi_camera_subscribe_event(event_handle, &subscribe);
LOG_O("Event subscript OK\n");
// 开始从channel中取出准备好的frame
csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_0);
csi_camera_channel_start(cam_handle, CSI_CAMERA_CHANNEL_1);
LOG_O("Channel start OK\n");
// 处理订阅的Event
csi_frame_s frame;
struct csi_camera_event event;
LOG_O("Starting get frame...\n");
while (running) {
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
csi_camera_get_event(event_handle, &event, timeout);
switch (event.type) {
case CSI_CAMERA_EVENT_TYPE_CAMERA:
switch (event.id) {
case CSI_CAMERA_EVENT_ERROR:
// do sth.
break;
default:
break;
}
case CSI_CAMERA_EVENT_TYPE_CHANNEL0:
switch (event.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
int read_frame_count = csi_camera_get_frame_count(cam_handle,
CSI_CAMERA_CHANNEL_0);
csi_camera_get_frame(cam_handle,CSI_CAMERA_CHANNEL_0, &frame, timeout);
// frame.image: {.width, .height, .pix_fmt, .dma-buf}
//show_frame_image(frame.image); // 伪代码
// frame.meta: {.count,
// .meta_data[]={meta_id, type,
// union{int_value, str_value, ...}}}
#ifdef PLATFORM_SIMULATOR
camera_action_image_display(&frame);
csi_camera_put_frame(&frame);
#endif
dump_camera_meta(&frame);
csi_frame_release(&frame);
break;
}
default:
break;
}
break;
case CSI_CAMERA_EVENT_TYPE_CHANNEL1:
switch (event.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
int read_frame_count = csi_camera_get_frame_count(cam_handle,
CSI_CAMERA_CHANNEL_1);
for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(cam_handle,CSI_CAMERA_CHANNEL_1, &frame, timeout);
// frame.image: {.width, .height, .pix_fmt, .dma-buf}
//show_frame_image(frame.image); // 伪代码
// frame.meta: {.count,
// .meta_data[]={meta_id, type,
// union{int_value, str_value, ...}}}
#ifdef PLATFORM_SIMULATOR
camera_action_image_display(&frame);
csi_camera_put_frame(&frame);
#endif
dump_camera_meta(&frame);
csi_frame_release(&frame);
}
break;
}
default:
break;
}
default:
break;
}
}
// 取消订阅某一个event, 也可以直接调用csi_camera_destory_event结束所有的订阅
subscribe.type = CSI_CAMERA_EVENT_TYPE_CHANNEL0;
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;;
csi_camera_unsubscribe_event(event_handle, &subscribe);
subscribe.type = CSI_CAMERA_EVENT_TYPE_CHANNEL1;
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;;
csi_camera_unsubscribe_event(event_handle, &subscribe);
subscribe.type = CSI_CAMERA_EVENT_TYPE_CAMERA;
subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
csi_camera_unsubscribe_event(event_handle, &subscribe);
csi_camera_destory_event(event_handle);
csi_camera_channel_stop(cam_handle, CSI_CAMERA_CHANNEL_0);
csi_camera_channel_close(cam_handle, CSI_CAMERA_CHANNEL_0);
csi_camera_close(cam_handle);
}
static void dump_camera_meta(csi_frame_s *frame)
{
int i;
if (frame->meta.type != CSI_META_TYPE_CAMERA)
return;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
int meta_count = meta_data->count;
csi_camrea_meta_unit_s meta_unit;
for (i = 0; i < meta_count; i++) {
csi_camera_frame_get_meta_unit(
&meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
printf("meta_id=%d, meta_type=%d, meta_value=%d",
meta_unit.id, meta_unit.type, meta_unit.int_value);
}
}

View File

@@ -0,0 +1,302 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <curses.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "camera_demo3"
#include <syslog.h>
#include "camera_manager.h"
#include "param.h"
#include "app_dialogs.h"
#include "menu_process.h"
cams_t *cam_session;
WINDOW *menubar;
WINDOW *messagebar;
WINDOW *win_border;
WINDOW *win_content;
void init_curses()
{
initscr(); /* init curses */
FILE *f = fopen("/dev/tty", "r+");
SCREEN *screen = newterm(NULL, f, f);
set_term(screen);
start_color(); /* color init, then init color pair */
init_pair(1, COLOR_WHITE, COLOR_BLACK);
init_pair(2, COLOR_BLACK, COLOR_WHITE);
init_pair(3, COLOR_RED, COLOR_WHITE);
init_pair(4, COLOR_WHITE, COLOR_BLUE); // menu font
init_pair(5, COLOR_YELLOW, COLOR_BLACK);
init_pair(6, COLOR_GREEN, COLOR_WHITE);
init_pair(7, COLOR_YELLOW, COLOR_WHITE);
curs_set(0); /* Cursor mode: 0:hide/1:normal/2:hilight */
noecho(); /* Do not display on screen */
keypad(stdscr, TRUE); /* allow keypad map */
}
void uninit_curses()
{
echo();
endwin();
}
void draw_menubar(WINDOW *menubar)
{
wbkgd(menubar, COLOR_PAIR(2));
for (int i = 0; i < atoi(param[0][0]); i++) {
wattron(menubar, COLOR_PAIR(3));
mvwprintw(menubar, 0, i * 14 + 2, "%1d.", i + 1);
wattroff(menubar, COLOR_PAIR(3));
mvwprintw(menubar, 0, i * 14 + 4, "%-12s", param[0][i + 1]);
}
}
WINDOW **draw_menu(int menu)
{
int i, start_col;
WINDOW **items;
items = (WINDOW **)malloc((atoi(param[menu][0]) + 1) * sizeof(WINDOW *));
start_col = (menu - 1) * 14 + 2;
items[0] = newwin(atoi(param[menu][0]) + 2, MENU_ITEM_MAX_LEN+2, 3, start_col);
wbkgd(items[0], COLOR_PAIR(2));
box(items[0], ACS_VLINE, ACS_HLINE);
for (i = 1; i <= atoi(param[menu][0]); i++) {
items[i] = subwin(items[0], 1, MENU_ITEM_MAX_LEN, 3 + i, start_col + 1);
wprintw(items[i], "%s", param[menu][i]);
}
wbkgd(items[1], COLOR_PAIR(4));
wrefresh(items[0]);
return items;
}
void delete_menu(WINDOW **items, int count)
{
int i;
for (i = 0; i < count; i++)
delwin(items[i]);
free(items);
}
int scroll_menu(WINDOW **items, int menu, int *menu_returned)
{
int key, count, selected = 0;
count = atoi(param[menu][0]);
LOG_D("Active: menu=%d, item=%d\n", menu, selected);
while (1) {
key = getch();
if (key == KEY_DOWN || key == KEY_UP) {
wbkgd(items[selected + 1], COLOR_PAIR(2));
wnoutrefresh(items[selected + 1]);
if (key == KEY_DOWN)
selected = (selected + 1) % count;
else
selected = (selected + count - 1) % count;
wbkgd(items[selected + 1], COLOR_PAIR(4));
wnoutrefresh(items[selected + 1]);
doupdate();
} else if (key == KEY_LEFT || key == KEY_RIGHT) {
delete_menu(items, count + 1);
touchwin(stdscr);
refresh();
if (key == KEY_LEFT) {
menu -= 1;
if (menu <= 0) menu = atoi(param[0][0]);
items = draw_menu(menu);
*menu_returned = menu;
LOG_D("Active: menu=%d, item=%d\n", *menu_returned, selected);
return scroll_menu(items, menu, menu_returned);
}
if (key == KEY_RIGHT) {
menu += 1;
if (menu > atoi(param[0][0])) menu = 1;
items = draw_menu(menu);
*menu_returned = menu;
LOG_D("Active: menu=%d, item=%d\n", *menu_returned, selected);
return scroll_menu(items, menu, menu_returned);
}
} else if (key == ESCAPE || key == '0' || key == 'q') {
delete_menu(items, count + 1);
return -1;
} else if (key == ENTER) {
delete_menu(items, count + 1);
return selected;
}
LOG_D("Active: menu=%d, item=%d\n", *menu_returned, selected);
}
}
/* ss: display string,
* status: 0:Normal, 1:OK, 2:Failed, 3:Warning */
void message(char *ss, int status)
{
int color_pair;
switch (status) {
case 1:
color_pair = 6; // GREEN:WHITE
break;
case 2:
color_pair = 3; // RED:WHITE
break;
case 3:
color_pair = 7; // YELLOW:WHITE
break;
default:
color_pair = 2; // BLACK:WHITE
break;
};
wbkgd(messagebar, COLOR_PAIR(2));
wattron(messagebar, COLOR_PAIR(color_pair));
mvwprintw(messagebar, 0, 0, "%80s", " ");
mvwprintw(messagebar, 0, 1, "%s", ss);
wattroff(messagebar, COLOR_PAIR(color_pair));
wrefresh(messagebar);
}
void copyright()
{
char *str[] = { "Copyright (C) 2021 Alibaba Group Holding Limited",
"Author: LuChongzhi, T-Head / IOT / OS Team",
"mailto:[chongzhi.lcz@alibaba-inc.com]"};
attron(A_UNDERLINE | COLOR_PAIR(1));
for (int i = 0; i < sizeof(str) / sizeof(char *); i++)
mvaddstr((WIN_ROWS - 2) / 2 + i, (WIN_COLS - strlen(str[0])) / 2, str[i]);
attroff(A_UNDERLINE | COLOR_PAIR(1));
refresh();
}
int main(int argc, char **argv)
{
int ret = -1;
int key;
WINDOW **menu_items;
if (get_param(argv[0])) {
LOG_E("\n Open %s.conf failed!\n", argv[0]);
goto LAB_EXIT;
}
if (camera_create_session(&cam_session) != 0 || cam_session == NULL) {
LOG_E("camera_create_session() failed\n");
goto LAB_EXIT;
}
init_curses();
if (init_dialog(NULL)) {
fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
goto LAB_EXIT_CURSES_INITED;
}
bkgd(COLOR_PAIR(1)); /* COLOR_WHITE, COLOR_BLACK */
/* set windows postion: (win, lines, cols, begin_y, begin_x) */
menubar = subwin(stdscr, 1, WIN_COLS, 1, 0); /* Menu bar line */
messagebar = subwin(stdscr, 1, WIN_COLS, WIN_ROWS - 1, 0); /* Bottom line */
win_border = subwin(stdscr, WIN_ROWS - 3, WIN_COLS, 2, 0); /* Content win with border */
win_content = subwin(stdscr, WIN_ROWS - 5, WIN_COLS - 2, 3, 1); /* Content win without border */
/* Set window title */
char str_title[81];
strcpy(str_title, "<<< CSI Camera Test Tool >>>");
wattron(stdscr, COLOR_PAIR(5));
mvwprintw(stdscr, 0, (80 - strlen(str_title)) / 2 - 1, "%s", str_title);
wattroff(stdscr, COLOR_PAIR(5));
/* Draw menu */
draw_menubar(menubar);
message("Use number key to choses menu. 'q' or '0' to Exit", 0);
/* Draw box border */
box(win_border, ACS_VLINE, ACS_HLINE);
/* Show copyright */
copyright();
refresh();
/* menu operate loop */
do {
key = wgetch(stdscr);
if (isdigit(key) && key > '0' && key <= atoi(param[0][0]) + '0') {
werase(messagebar);
wrefresh(messagebar);
int menu_init = key - '0'; // first press menu id
int menu_final = menu_init; // return from scroll_menu
menu_items = draw_menu(menu_init);
int item_selected = scroll_menu(menu_items, menu_init, &menu_final);
LOG_D("menu_final=%d, selected_item=%d\n",
menu_final, item_selected);
switch(menu_final) {
case MENU_CAMERA:
menu_camera_process(item_selected);
break;
case MENU_CHANNEL:
menu_channel_process(item_selected);
break;
case MENU_EVENT_RUN:
menu_event_run_process(item_selected);
break;
default:
LOG_W("Not supported menu: %d\n", menu_final);
break;
}
if (item_selected == 13) {
LOG_D("Test dialog_inputbox\n");
dialog_inputbox("inputbox", "prompt", 16, 80,
"const char init");
}
touchwin(stdscr);
refresh();
} else if (key == KEY_RESIZE) {
box(win_border, ACS_VLINE, ACS_HLINE);
wrefresh(messagebar);
}
} while (key != 'q' && key != '0');
ret = 0;
LAB_EXIT_WIN_CREATED:
delwin(win_content);
delwin(win_border);
delwin(menubar);
delwin(messagebar);
LAB_EXIT_CURSES_INITED:
uninit_curses();
LAB_EXIT_CAM_MGR_CREATED:
camera_destory_session(&cam_session);
LAB_EXIT:
return ret;
}

View File

@@ -0,0 +1,11 @@
#
# 格式为: 菜单号|项目个数|项目名称......
# 菜单数量最大为10个
#
0|5|Camera|Channel|Event&Run|Capture|Help|
1|5|List Cameras|Open Camera|Set Mode|Set Property|Close Camera|
2|3|List Channels|Open Channel|Close Channel|
3|2|Subscribe&Action|Start/Stop|
4|4|menu41|menu42|menu43|menu44|
5|2|menu51|menu52|
6|1|menu61|

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __APP_DIALOGS_H__
#define __APP_DIALOGS_H__
#include <curses.h>
#include <csi_camera_property.h>
#include "dialog.h"
#include "param.h"
#include "camera_manager.h"
extern cams_t *cam_session; /* camera manager */
/* curses window */
#define WIN_COLS 100
#define WIN_ROWS 40
/* key defination */
#define ENTER 10
#define ESCAPE 27
/* windoes created by main */
extern WINDOW *menubar;
extern WINDOW *messagebar;
extern WINDOW *win_border;
extern WINDOW *win_content;
void message(char *ss, int status);
int dialog_camera_list(void);
int dialog_camera_open(void);
int dialog_camera_set_mode(void);
int dialog_camera_property_list(void);
int dialog_camera_close(void);
int dialog_camera_property_boolean(csi_camera_property_description_s *property);
int dialog_camera_property_integer(csi_camera_property_description_s *property);
int dialog_camera_property_enum(csi_camera_property_description_s *property);
int dialog_camera_property_bitmask(csi_camera_property_description_s *property);
int dialog_channel_list(void);
int dialog_channel_select(csi_camera_channel_cfg_s **selected_chn, int action);
int dialog_channel_open(csi_camera_channel_cfg_s *channel);
int dialog_event_subscribe_action_list(camera_event_action_union_t **event_action);
int dialog_event_subscribe_action_camera(camera_event_action_union_t *event_action);
int dialog_event_subscribe_action_channel(camera_event_action_union_t *event_action);
int dialog_channel_run(void);
#endif /* __APP_DIALOGS_H__ */

View File

@@ -0,0 +1,17 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "camera_ops"
#include <syslog.h>
#include "camera_ops.h"

View File

@@ -0,0 +1,18 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CAMERA_OPS_H__
#define __CAMERA_OPS_H__
#include <stdio.h>
#include <csi_camera.h>
#include <camera_manager.h>
#endif /* __CAMERA_OPS_H__ */

View File

@@ -0,0 +1,337 @@
/*
* checklist.c -- implements the checklist box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
#include "app_dialogs.h"
#define LOG_LEVEL 2
#define LOG_PREFIX "camera_demo3"
#include <syslog.h>
static int list_width, check_x, item_x;
/*
* Print list item
*/
static void print_item(WINDOW * win, int choice, int selected)
{
int i;
char *list_item = malloc(list_width + 1);
strncpy(list_item, item_str(), list_width - item_x);
list_item[list_width - item_x] = '\0';
/* Clear 'residue' of last item */
wattrset(win, dlg.menubox.atr);
wmove(win, choice, 0);
for (i = 0; i < list_width; i++)
waddch(win, ' ');
wmove(win, choice, check_x);
wattrset(win, selected ? dlg.check_selected.atr
: dlg.check.atr);
if (!item_is_tag(':'))
wprintw(win, "[%c]", item_is_tag('*') ? '*' : ' ');
wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
mvwaddch(win, choice, item_x, list_item[0]);
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
waddstr(win, list_item + 1);
if (selected) {
wmove(win, choice, check_x + 1);
wrefresh(win);
}
free(list_item);
}
/*
* Print the scroll indicators.
*/
static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
int y, int x, int height)
{
wmove(win, y, x);
if (scroll > 0) {
wattrset(win, dlg.uarrow.atr);
waddch(win, ACS_UARROW);
waddstr(win, "[-]");
} else {
wattrset(win, dlg.menubox.atr);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
}
y = y + height + 1;
wmove(win, y, x);
if ((height < item_no) && (scroll + choice < item_no - 1)) {
wattrset(win, dlg.darrow.atr);
waddch(win, ACS_DARROW);
waddstr(win, "[+]");
} else {
wattrset(win, dlg.menubox_border.atr);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
}
}
/*
* Display the termination buttons
*/
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
{
int x = width / 2 - 11;
int y = height - 2;
print_button(dialog, gettext("Select"), y, x - 7, selected == 0);
print_button(dialog, gettext("Return"), y, x + 7, selected == 1);
print_button(dialog, gettext(" Help "), y, x + 21, selected == 2);
wmove(dialog, y, x - 7 + 1 + 14 * selected);
wrefresh(dialog);
}
/*
* Display a dialog box with a list of options that can be turned on or off
* in the style of radiolist (only one option turned on at a time).
*/
int dialog_checkbox(const char *title, const char *prompt, int height,
int width, int list_height, int init_choice)
{
int i, x, y, box_x, box_y;
int key = 0, button = 0, choice = init_choice, scroll = 0, max_choice;
WINDOW *dialog, *list;
do_resize:
if (WIN_ROWS < (height + CHECKLIST_HEIGTH_MIN)) {
LOG_E("WIN_ROWS(%d) < (height(%d) + CHECKLIST_HEIGTH_MIN(%d)\n",
WIN_ROWS, height, CHECKLIST_HEIGTH_MIN);
return -ERRDISPLAYTOOSMALL;
}
if (WIN_COLS < (width + CHECKLIST_WIDTH_MIN)) {
LOG_E("WIN_COLS(%d) < (width(%d) + CHECKLIST_WIDTH_MIN(%d)\n",
WIN_COLS, width, CHECKLIST_WIDTH_MIN);
return -ERRDISPLAYTOOSMALL;
}
max_choice = MIN(list_height, item_count());
/* center dialog box on screen */
x = (WIN_COLS - width) / 2;
y = (WIN_ROWS - height) / 2;
draw_shadow(stdscr, y, x, height, width);
dialog = newwin(height, width, y, x);
keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE);
print_title(dialog, title, width);
wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3);
list_width = width - 6;
box_y = height - list_height - 5;
box_x = (width - list_width) / 2 - 1;
/* create new window for the list */
list = subwin(dialog, list_height, list_width, y + box_y + 1,
x + box_x + 1);
keypad(list, TRUE);
/* draw a box around the list items */
draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
dlg.menubox_border.atr, dlg.menubox.atr);
/* Find length of longest item in order to center checklist */
check_x = 0;
item_foreach()
check_x = MAX(check_x, strlen(item_str()) + 4);
check_x = MIN(check_x, list_width);
check_x = (list_width - check_x) / 2 - 4;
item_x = check_x + 4;
if (choice >= list_height) {
scroll = choice - list_height + 1;
choice -= scroll;
}
/* Print the list */
for (i = 0; i < max_choice; i++) {
item_set(scroll + i);
print_item(list, i, i == choice);
}
print_arrows(dialog, choice, item_count(), scroll,
box_y, box_x + check_x + 5, list_height);
print_buttons(dialog, height, width, 0);
wnoutrefresh(dialog);
wnoutrefresh(list);
doupdate();
while (key != KEY_ESC) {
key = wgetch(dialog);
for (i = 0; i < max_choice; i++) {
item_set(i + scroll);
if (toupper(key) == toupper(item_str()[0]))
break;
}
if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-') {
if (key == KEY_UP || key == '-') {
if (!choice) {
if (!scroll)
continue;
/* Scroll list down */
if (list_height > 1) {
/* De-highlight current first item */
item_set(scroll);
print_item(list, 0, FALSE);
scrollok(list, TRUE);
wscrl(list, -1);
scrollok(list, FALSE);
}
scroll--;
item_set(scroll);
print_item(list, 0, TRUE);
print_arrows(dialog, choice, item_count(),
scroll, box_y, box_x + check_x + 5, list_height);
wnoutrefresh(dialog);
wrefresh(list);
continue; /* wait for another key press */
} else
i = choice - 1;
} else if (key == KEY_DOWN || key == '+') {
if (choice == max_choice - 1) {
if (scroll + choice >= item_count() - 1)
continue;
/* Scroll list up */
if (list_height > 1) {
/* De-highlight current last item before scrolling up */
item_set(scroll + max_choice - 1);
print_item(list,
max_choice - 1,
FALSE);
scrollok(list, TRUE);
wscrl(list, 1);
scrollok(list, FALSE);
}
scroll++;
item_set(scroll + max_choice - 1);
print_item(list, max_choice - 1, TRUE);
print_arrows(dialog, choice, item_count(),
scroll, box_y, box_x + check_x + 5, list_height);
wnoutrefresh(dialog);
wrefresh(list);
continue; /* wait for another key press */
} else
i = choice + 1;
}
if (i != choice) {
/* De-highlight current item */
item_set(scroll + choice);
print_item(list, choice, FALSE);
/* Highlight new item */
choice = i;
item_set(scroll + choice);
print_item(list, choice, TRUE);
wnoutrefresh(dialog);
wrefresh(list);
}
continue; /* wait for another key press */
}
switch (key) {
case 'H':
case 'h':
button = 1;
/* fall-through */
case 'S':
case 's':
case ' ':
case '\n':
item_set(scroll + choice);
if (item_is_selected()) {
item_set_selected(0);
}
else {
item_set_selected(1);
}
delwin(list);
delwin(dialog);
return button;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 2 : (button > 2 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh(dialog);
break;
case 'X':
case 'x':
key = KEY_ESC;
break;
case KEY_ESC:
key = on_key_esc(dialog);
break;
case KEY_RESIZE:
delwin(list);
delwin(dialog);
on_key_resize();
goto do_resize;
}
/* Now, update everything... */
doupdate();
}
delwin(list);
delwin(dialog);
return key; /* ESC pressed */
}

View File

@@ -0,0 +1,355 @@
/*
* checklist.c -- implements the checklist box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
#include "app_dialogs.h"
#define LOG_LEVEL 2
#define LOG_PREFIX "camera_demo3"
#include <syslog.h>
static int list_width, check_x, item_x;
/*
* Print list item
*/
static void print_item(WINDOW * win, int choice, int selected)
{
int i;
char *list_item = malloc(list_width + 1);
strncpy(list_item, item_str(), list_width - item_x);
list_item[list_width - item_x] = '\0';
/* Clear 'residue' of last item */
wattrset(win, dlg.menubox.atr);
wmove(win, choice, 0);
for (i = 0; i < list_width; i++)
waddch(win, ' ');
wmove(win, choice, check_x);
wattrset(win, selected ? dlg.check_selected.atr
: dlg.check.atr);
if (!item_is_tag(':'))
wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
mvwaddch(win, choice, item_x, list_item[0]);
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
waddstr(win, list_item + 1);
if (selected) {
wmove(win, choice, check_x + 1);
wrefresh(win);
}
free(list_item);
}
/*
* Print the scroll indicators.
*/
static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
int y, int x, int height)
{
wmove(win, y, x);
if (scroll > 0) {
wattrset(win, dlg.uarrow.atr);
waddch(win, ACS_UARROW);
waddstr(win, "(-)");
} else {
wattrset(win, dlg.menubox.atr);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
}
y = y + height + 1;
wmove(win, y, x);
if ((height < item_no) && (scroll + choice < item_no - 1)) {
wattrset(win, dlg.darrow.atr);
waddch(win, ACS_DARROW);
waddstr(win, "(+)");
} else {
wattrset(win, dlg.menubox_border.atr);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
}
}
/*
* Display the termination buttons
*/
static void print_buttons(WINDOW * dialog, int height, int width, int selected,
char *button_names[], int button_count)
{
int x = width / 2 - 11;
int y = height - 2;
if (button_names == NULL) {
print_button(dialog, gettext("Select"), y, x, selected == 0);
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
} else {
for (int i = 0; i < button_count; i++) {
print_button(dialog, gettext(button_names[i]), y, x + 14*i, selected == i);
}
}
wmove(dialog, y, x + 1 + 14 * selected);
wrefresh(dialog);
}
/*
* Display a dialog box with a list of options that can be turned on or off
* in the style of radiolist (only one option turned on at a time).
*/
int dialog_checklist(const char *title, const char *prompt, int height,
int width, int list_height, char *button_names[], int button_count)
{
int i, x, y, box_x, box_y;
int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
WINDOW *dialog, *list;
/* which item to highlight */
item_foreach() {
if (item_is_tag('X'))
choice = item_n();
if (item_is_selected()) {
choice = item_n();
break;
}
}
do_resize:
if (WIN_ROWS < (height + CHECKLIST_HEIGTH_MIN)) {
LOG_E("WIN_ROWS(%d) < (height(%d) + CHECKLIST_HEIGTH_MIN(%d)\n",
WIN_ROWS, height, CHECKLIST_HEIGTH_MIN);
return -ERRDISPLAYTOOSMALL;
}
if (WIN_COLS < (width + CHECKLIST_WIDTH_MIN)) {
LOG_E("WIN_COLS(%d) < (width(%d) + CHECKLIST_WIDTH_MIN(%d)\n",
WIN_COLS, width, CHECKLIST_WIDTH_MIN);
return -ERRDISPLAYTOOSMALL;
}
max_choice = MIN(list_height, item_count());
/* center dialog box on screen */
x = (WIN_COLS - width) / 2;
y = (WIN_ROWS - height) / 2;
draw_shadow(stdscr, y, x, height, width);
dialog = newwin(height, width, y, x);
keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE);
print_title(dialog, title, width);
wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3);
list_width = width - 6;
box_y = height - list_height - 5;
box_x = (width - list_width) / 2 - 1;
/* create new window for the list */
list = subwin(dialog, list_height, list_width, y + box_y + 1,
x + box_x + 1);
keypad(list, TRUE);
/* draw a box around the list items */
draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
dlg.menubox_border.atr, dlg.menubox.atr);
/* Find length of longest item in order to center checklist */
check_x = 0;
item_foreach()
check_x = MAX(check_x, strlen(item_str()) + 4);
check_x = MIN(check_x, list_width);
check_x = (list_width - check_x) / 2 - 4;
item_x = check_x + 4;
if (choice >= list_height) {
scroll = choice - list_height + 1;
choice -= scroll;
}
/* Print the list */
for (i = 0; i < max_choice; i++) {
item_set(scroll + i);
print_item(list, i, i == choice);
}
print_arrows(dialog, choice, item_count(), scroll,
box_y, box_x + check_x + 5, list_height);
print_buttons(dialog, height, width, 0, button_names, button_count);
wnoutrefresh(dialog);
wnoutrefresh(list);
doupdate();
while (key != KEY_ESC) {
key = wgetch(dialog);
for (i = 0; i < max_choice; i++) {
item_set(i + scroll);
if (toupper(key) == toupper(item_str()[0]))
break;
}
if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-') {
if (key == KEY_UP || key == '-') {
if (!choice) {
if (!scroll)
continue;
/* Scroll list down */
if (list_height > 1) {
/* De-highlight current first item */
item_set(scroll);
print_item(list, 0, FALSE);
scrollok(list, TRUE);
wscrl(list, -1);
scrollok(list, FALSE);
}
scroll--;
item_set(scroll);
print_item(list, 0, TRUE);
print_arrows(dialog, choice, item_count(),
scroll, box_y, box_x + check_x + 5, list_height);
wnoutrefresh(dialog);
wrefresh(list);
continue; /* wait for another key press */
} else
i = choice - 1;
} else if (key == KEY_DOWN || key == '+') {
if (choice == max_choice - 1) {
if (scroll + choice >= item_count() - 1)
continue;
/* Scroll list up */
if (list_height > 1) {
/* De-highlight current last item before scrolling up */
item_set(scroll + max_choice - 1);
print_item(list,
max_choice - 1,
FALSE);
scrollok(list, TRUE);
wscrl(list, 1);
scrollok(list, FALSE);
}
scroll++;
item_set(scroll + max_choice - 1);
print_item(list, max_choice - 1, TRUE);
print_arrows(dialog, choice, item_count(),
scroll, box_y, box_x + check_x + 5, list_height);
wnoutrefresh(dialog);
wrefresh(list);
continue; /* wait for another key press */
} else
i = choice + 1;
}
if (i != choice) {
/* De-highlight current item */
item_set(scroll + choice);
print_item(list, choice, FALSE);
/* Highlight new item */
choice = i;
item_set(scroll + choice);
print_item(list, choice, TRUE);
wnoutrefresh(dialog);
wrefresh(list);
}
continue; /* wait for another key press */
}
switch (key) {
case 'H':
case 'h':
button = 1;
/* fall-through */
case 'S':
case 's':
case ' ':
case '\n':
item_foreach()
item_set_selected(0);
item_set(scroll + choice);
item_set_selected(1);
delwin(list);
delwin(dialog);
return button;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
if (button_names != NULL || button_count > 0) {
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? (button_count - 1) : (button > (button_count - 1) ? 0 : button);
} else {
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 1 : (button > 1 ? 0 : button);
}
print_buttons(dialog, height, width, button, button_names, button_count);
wrefresh(dialog);
break;
case 'X':
case 'x':
key = KEY_ESC;
break;
case KEY_ESC:
key = on_key_esc(dialog);
break;
case KEY_RESIZE:
delwin(list);
delwin(dialog);
on_key_resize();
goto do_resize;
}
/* Now, update everything... */
doupdate();
}
delwin(list);
delwin(dialog);
return key; /* ESC pressed */
}

View File

@@ -0,0 +1,276 @@
/*
* dialog.h -- common declarations for all dialog modules
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __DIALOG_H__
#define __DIALOG_H__
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
////////// lucz add begin
#define N_(text) (text)
////////// lucz add end
#ifndef KBUILD_NO_NLS
# include <libintl.h>
#else
# define gettext(Msgid) ((const char *) (Msgid))
#endif
#ifdef __sun__
#define CURS_MACROS
#endif
#include <ncurses.h>
/*
* Colors in ncurses 1.9.9e do not work properly since foreground and
* background colors are OR'd rather than separately masked. This version
* of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
* with standard curses. The simplest fix (to make this work with standard
* curses) uses the wbkgdset() function, not used in the original hack.
* Turn it off if we're building with 1.9.9e, since it just confuses things.
*/
#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
#define OLD_NCURSES 1
#undef wbkgdset
#define wbkgdset(w,p) /*nothing */
#else
#define OLD_NCURSES 0
#endif
#define TR(params) _tracef params
#define KEY_ESC 27
#define TAB 9
#define MAX_LEN 2048
#define BUF_SIZE (10*1024)
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
#ifndef ACS_ULCORNER
#define ACS_ULCORNER '+'
#endif
#ifndef ACS_LLCORNER
#define ACS_LLCORNER '+'
#endif
#ifndef ACS_URCORNER
#define ACS_URCORNER '+'
#endif
#ifndef ACS_LRCORNER
#define ACS_LRCORNER '+'
#endif
#ifndef ACS_HLINE
#define ACS_HLINE '-'
#endif
#ifndef ACS_VLINE
#define ACS_VLINE '|'
#endif
#ifndef ACS_LTEE
#define ACS_LTEE '+'
#endif
#ifndef ACS_RTEE
#define ACS_RTEE '+'
#endif
#ifndef ACS_UARROW
#define ACS_UARROW '^'
#endif
#ifndef ACS_DARROW
#define ACS_DARROW 'v'
#endif
/* error return codes */
#define ERRDISPLAYTOOSMALL (KEY_MAX + 1)
/*
* Color definitions
*/
struct dialog_color {
chtype atr; /* Color attribute */
int fg; /* foreground */
int bg; /* background */
int hl; /* highlight this item */
};
struct subtitle_list {
struct subtitle_list *next;
const char *text;
};
struct dialog_info {
const char *backtitle;
struct subtitle_list *subtitles;
struct dialog_color screen;
struct dialog_color shadow;
struct dialog_color dialog;
struct dialog_color title;
struct dialog_color border;
struct dialog_color button_active;
struct dialog_color button_inactive;
struct dialog_color button_key_active;
struct dialog_color button_key_inactive;
struct dialog_color button_label_active;
struct dialog_color button_label_inactive;
struct dialog_color inputbox;
struct dialog_color inputbox_border;
struct dialog_color searchbox;
struct dialog_color searchbox_title;
struct dialog_color searchbox_border;
struct dialog_color position_indicator;
struct dialog_color menubox;
struct dialog_color menubox_border;
struct dialog_color item;
struct dialog_color item_selected;
struct dialog_color tag;
struct dialog_color tag_selected;
struct dialog_color tag_key;
struct dialog_color tag_key_selected;
struct dialog_color check;
struct dialog_color check_selected;
struct dialog_color uarrow;
struct dialog_color darrow;
};
/*
* Global variables
*/
extern struct dialog_info dlg;
extern char dialog_input_result[];
extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
/*
* Function prototypes
*/
/* item list as used by checklist and menubox */
void item_reset(void);
void item_make(const char *fmt, ...);
void item_add_str(const char *fmt, ...);
void item_set_tag(char tag);
void item_set_int(int int_value);
void item_set_data(void *p);
void item_set_selected(int val);
int item_activate_selected(void);
int item_activate_selected_pos(void);
void *item_data(void);
char item_tag(void);
int item_int(void);
/* item list manipulation for lxdialog use */
#define MAXITEMSTR 200
struct dialog_item {
char str[MAXITEMSTR]; /* prompt displayed */
char tag;
void *data; /* pointer to menu item - used by menubox+checklist */
int int_value; /* the int value of the item */
int selected; /* Set to 1 by dialog_*() function if selected. */
};
/* list of lialog_items */
struct dialog_list {
struct dialog_item node;
struct dialog_list *next;
};
extern struct dialog_list *item_cur;
extern struct dialog_list item_nil;
extern struct dialog_list *item_head;
int item_count(void);
void item_set(int n);
int item_n(void);
const char *item_str(void);
int item_is_selected(void);
int item_is_tag(char tag);
#define item_foreach() \
for (item_cur = item_head ? item_head: item_cur; \
item_cur && (item_cur != &item_nil); item_cur = item_cur->next)
/* generic key handlers */
int on_key_esc(WINDOW *win);
int on_key_resize(void);
/* minimum (re)size values */
#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */
#define CHECKLIST_WIDTH_MIN 6
#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */
#define INPUTBOX_WIDTH_MIN 2
#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */
#define MENUBOX_WIDTH_MIN 65
#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */
#define TEXTBOX_WIDTH_MIN 8
#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */
#define YESNO_WIDTH_MIN 4
#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */
#define WINDOW_WIDTH_MIN 80
int init_dialog(const char *backtitle);
void set_dialog_backtitle(const char *backtitle);
void set_dialog_subtitles(struct subtitle_list *subtitles);
void end_dialog(int x, int y);
void attr_clear(WINDOW * win, int height, int width, chtype attr);
void dialog_clear(void);
void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
void print_button(WINDOW * win, const char *label, int y, int x, int selected);
void print_title(WINDOW *dialog, const char *title, int width);
void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
chtype border);
void draw_shadow(WINDOW * win, int y, int x, int height, int width);
int first_alpha(const char *string, const char *exempt);
int dialog_yesno(const char *title, const char *prompt, int height, int width);
int dialog_msgbox(const char *title, const char *prompt, int height,
int width, int pause);
typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
*_data);
int dialog_textbox(const char *title, char *tbuf, int initial_height,
int initial_width, int *keys, int *_vscroll, int *_hscroll,
update_text_fn update_text, void *data);
int dialog_textbox_simple(const char *title, char *tbuf, int initial_height, int initial_width);
int dialog_menu(const char *title, const char *prompt, int height, int width,
const void *selected, int selected_pos, int *s_scroll,
char *button_names[], int button_count);
int dialog_checklist(const char *title, const char *prompt, int height,
int width, int list_height, char *button_names[], int button_count);
int dialog_checkbox(const char *title, const char *prompt, int height,
int width, int list_height, int init_choice);
int dialog_inputbox(const char *title, const char *prompt, int height,
int width, const char *init);
/*
* This is the base for fictitious keys, which activate
* the buttons.
*
* Mouse-generated keys are the following:
* -- the first 32 are used as numbers, in addition to '0'-'9'
* -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
* -- uppercase chars are used to invoke the button (M_EVENT + 'O')
*/
#define M_EVENT (KEY_MAX+1)
#endif /* __DIALOG_H__ */

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_close_camera"
#include <syslog.h>
#include <camera_manager.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
int dialog_camera_close(void)
{
int ret_key = KEY_ESC;
int ret;
if (cam_session == NULL) {
LOG_E("cam_session is NULL\n");
return -1;
}
if (cam_session->camera_handle == NULL) {
LOG_I("The camera has not been opened yet\n");
dialog_textbox_simple("Infomation", "There's No camera opened yet", 10, 40);
return -1;
}
char str_buf[256];
int cam_id = cam_session->camera_id;
snprintf(str_buf, sizeof(str_buf),
"The camera below is to be closed:\n"
"\t id=%d \n\t name='%s' \n\t device='%s' \n\t bus='%s'\n",
cam_id,
cam_session->camera_infos.info[cam_id].camera_name,
cam_session->camera_infos.info[cam_id].device_name,
cam_session->camera_infos.info[cam_id].bus_info);
ret_key = dialog_yesno("Infomation", str_buf, 10, 50);
LOG_D("dialog_yesno() return %d\n", ret);
if (ret_key != 0) { // 0 is the button position of 'yes'
LOG_D("close camera is canceled\n");
return 0;
}
ret = camera_close(cam_session);
if (ret != 0) {
LOG_E("camera_close() failed\n");
ret = -1;
}
snprintf(str_buf, sizeof(str_buf),
"The camera close %s: {%d, %s, %s, %s}\n",
(ret == 0) ? "OK" : "Failed",
cam_id,
cam_session->camera_infos.info[cam_id].camera_name,
cam_session->camera_infos.info[cam_id].device_name,
cam_session->camera_infos.info[cam_id].bus_info);
message(str_buf, (ret == 0) ? 1 : 2);
return ret;
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_camera_list"
#include <syslog.h>
#include <camera_manager.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
int dialog_camera_list(void)
{
int ret_key = KEY_ESC;
int ret;
if (cam_session == NULL) {
LOG_E("cam_session is NULL\n");
return KEY_ESC;
}
/* Get camera list */
if (camera_query_list(cam_session) != 0) {
LOG_E("camera_query_list() failed\n");
return KEY_ESC;
}
char str_buf[1024] = "";
char str_item[256];
/* Prepare for checklist nodes */
csi_camera_infos_s *cam_infos = &cam_session->camera_infos;
for (int i = 0; i < cam_infos->count; i++) {
csi_camera_info_s *info = &(cam_infos->info[i]);
snprintf(str_item, sizeof(str_item),
"Camera[%d] info:\n"
"\t name = %s\n"
"\t dev = %s\n"
"\t bus = %s\n",
i,
info->camera_name,
info->device_name,
info->bus_info);
strcat(str_buf, str_item);
strcat(str_buf, "\t caps = ");
for (unsigned int j = 1; j < 0x80000000; j = j << 1) {
switch (info->capabilities & j) {
case CSI_CAMERA_CAP_VIDEO_CAPTURE:
strcat(str_buf,"VIDEO_CAPTURE | ");
break;
case CSI_CAMERA_CAP_META_CAPTURE:
strcat(str_buf, "META_CAPTURE | ");
break;
default:
if (info->capabilities & j) {
strcat(str_buf, "Unknown");
}
break;
}
}
strcat(str_buf, "\n\n");
}
dialog_textbox_simple("System Camera List",
str_buf,
20, //int initial_height,
80); //int initial_width
return ret;
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_open_camera"
#include <syslog.h>
#include <camera_manager.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
int dialog_camera_open(void)
{
int ret_key = KEY_ESC;
int ret;
if (cam_session == NULL) {
LOG_E("cam_session is NULL\n");
return KEY_ESC;
}
if (cam_session->camera_handle != NULL) {
csi_camera_info_s *info =
&(cam_session->camera_infos.info[cam_session->camera_id]);
char textbox_content[256];
snprintf(textbox_content, sizeof(textbox_content),
"Please close camera below first:\n"
" camera: %s\n device:%s\n bus:%s\n",
info->camera_name, info->device_name, info->bus_info);
dialog_textbox("Error",
textbox_content,
10, //int initial_height,
40, //int initial_width,
(int []) {0}, //int *keys,
NULL,
NULL,
NULL, //update_text_fn update_text,
NULL /*void *data*/);
return 0;
}
again:
item_reset();
if (camera_query_list(cam_session) != 0) {
LOG_E("camera_query_list() failed\n");
return KEY_ESC;
}
/* Prepare for checklist nodes */
csi_camera_infos_s *cam_infos = &cam_session->camera_infos;
for (int i = 0; i < cam_infos->count; i++) {
csi_camera_info_s *info = &(cam_infos->info[i]);
item_make("%-16s", info->camera_name);
item_add_str("%-12s %s",
info->device_name,
info->bus_info);
item_set_data(info); // store cam_info pointer
if (i == cam_session->camera_id) {
item_set_tag('X');
item_set_selected(1);
} else {
item_set_tag(' ');
item_set_selected(0);
}
}
ret = dialog_checklist(
"Select Camera to open", /* Title */
"Select the camera to open. "
"Press 'h' to get capabilities details",
CHECKLIST_HEIGTH_MIN + 10,
WIN_COLS - CHECKLIST_WIDTH_MIN - 16,
8,
NULL, 0);
int cam_id;
int selected = item_activate_selected();
LOG_D("ret=%d, selected=%s\n", ret, selected ? "true" : "false");
char str_buf[256];
switch (ret) {
case 0: // item is selected
if (!selected)
break;
/* Show operation result */
cam_id = item_activate_selected_pos();
//char str_buf[256];
bool opened = (camera_open(cam_session, cam_id) == 0);
snprintf(str_buf, sizeof(str_buf),
"Open the below camera %s:\n"
"\t id=%d \n\t name='%s' \n\t device='%s' \n\t bus='%s'\n",
opened ? "OK" : "Failed",
cam_id,
cam_session->camera_infos.info[cam_id].camera_name,
cam_session->camera_infos.info[cam_id].device_name,
cam_session->camera_infos.info[cam_id].bus_info);
dialog_textbox_simple("Infomation", str_buf, 10, 40);
LOG_I("csi_camera_infos_s.info[%d] is opened %s\n",
cam_id, opened ? "OK" : "Failed");
/* Show message bar */
snprintf(str_buf, sizeof(str_buf),
"The camera open %s: {%d, %s, %s, %s}\n",
opened ? "OK" : "Failed",
cam_id,
cam_session->camera_infos.info[cam_id].camera_name,
cam_session->camera_infos.info[cam_id].device_name,
cam_session->camera_infos.info[cam_id].bus_info);
message(str_buf, opened ? 1 : 2);
break;
case 1: // need help
cam_id = item_n();
//char str_buf[256];
snprintf(str_buf, sizeof(str_buf),
"Camera info:\n"
"\t id=%d \n\t name='%s' \n\t device='%s' \n\t bus='%s'\n",
cam_id,
cam_session->camera_infos.info[cam_id].camera_name,
cam_session->camera_infos.info[cam_id].device_name,
cam_session->camera_infos.info[cam_id].bus_info);
dialog_textbox_simple("Infomation", str_buf, 10, 40);
goto again;
case KEY_ESC: // specific KEY
break;
case -ERRDISPLAYTOOSMALL: // error
default:
LOG_W("Oops? why return ret=%d\n", ret);
break;
}
LOG_D("ret=%d\n", ret);
return 0;
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_enum"
#include <syslog.h>
#include <camera_manager.h>
#include <csi_camera_platform_spec.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
int dialog_camera_property_bitmask(csi_camera_property_description_s *property)
{
int ret_key = KEY_ESC;
if (property == NULL) {
LOG_W("property is NULL\n");
return KEY_ESC;
}
char *title = property->name;
char *prompt = "Please set camera property";
int item_pos = 0;
again:
item_reset();
const camera_spec_bitmasks_t *bitmasks_array = camera_spec_get_bitmask_array(property->id);
if (bitmasks_array == NULL)
return KEY_ESC;
for (int i = 0; i < bitmasks_array->count; i++) {
item_make("bit-%02d: %s", bitmasks_array->bitmask[i],
camera_string_bitmask_name(property->id, bitmasks_array->bitmask[i]));
item_add_str("%s",
(bitmasks_array->bitmask[i] & property->default_value.enum_value) ? " (default)" : "");
if (bitmasks_array->bitmask[i] & property->value.enum_value) {
item_set_selected(1);
item_set_tag('*');
}
else {
item_set_selected(0);
item_set_tag(' ');
}
}
int list_height = MIN(bitmasks_array->count + 1, 8);
ret_key = dialog_checkbox(
title, prompt,
CHECKLIST_HEIGTH_MIN + list_height + 2,
WIN_COLS - CHECKLIST_WIDTH_MIN - 32,
list_height, item_pos);
LOG_D("dialog_checkbox() ret_key=%d\n", ret_key);
if (ret_key == KEY_ESC) {
return KEY_ESC;
} else if (ret_key == 0) {/* select */
item_pos = item_n();
int bitmask_value = bitmasks_array->bitmask[item_n()];
if (item_is_selected()) {
property->value.bitmask_value |= bitmask_value;
} else {
property->value.bitmask_value &= ~bitmask_value;
}
int enum_id = bitmasks_array->bitmask[item_n()];
LOG_D("%s item: pos=%d, enum=%d-%s, bitmask_value=%08x\n",
item_is_selected() ? "Select" : "Unselect",
item_n(), enum_id,
camera_string_bitmask_name(property->id, enum_id),
property->value.bitmask_value);
goto again;
return ret_key;
} else if (ret_key == 1) {/* help */
LOG_W("Help does not support yet\n");
return ret_key;
} else {
LOG_E("Unknown return value: %d\n", ret_key);
return KEY_ESC;
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_boolean"
#include <syslog.h>
#include "param.h"
#include "app_dialogs.h"
#include <camera_manager.h>
extern cams_t *cam_session;
int dialog_camera_property_boolean(csi_camera_property_description_s *property)
{
int ret_key = KEY_ESC;
if (property == NULL) {
LOG_W("property is NULL\n");
return KEY_ESC;
}
item_reset();
char *title = property->name;
char *prompt = "Please set camera property";
item_reset();
item_make("true");
if (property->default_value.bool_value)
item_add_str("(default)");
if (property->value.bool_value) {
item_set_tag('X');
item_set_selected(1);
} else {
item_set_tag(' ');
item_set_selected(0);
}
item_make("false");
if (!property->default_value.bool_value)
item_add_str(" (default)");
if (!property->value.bool_value) {
item_set_tag('X');
item_set_selected(1);
} else {
item_set_tag(' ');
item_set_selected(0);
}
ret_key = dialog_checklist(
title, prompt,
CHECKLIST_HEIGTH_MIN + 4,
WIN_COLS - CHECKLIST_WIDTH_MIN - 32,
2,
NULL, 0);
LOG_D("dialog_checklist() ret_key=%d\n", ret_key);
if (ret_key == KEY_ESC) {
return KEY_ESC;
} else if (ret_key == 0) {/* select */
LOG_D("select item: %d, means '%s'\n", item_n(),
(item_n() == 0) ? "true" : "false");
property->value.bool_value = (item_n() == 0) ? true : false;
return ret_key;
} else if (ret_key == 1) {/* help */
LOG_W("Help does not support yet\n");
return ret_key;
} else {
LOG_E("Unknown return value: %d\n", ret_key);
return KEY_ESC;
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_enum"
#include <syslog.h>
#include <curses.h>
#include <csi_camera_platform_spec.h>
#include <camera_manager.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
int dialog_camera_property_enum(csi_camera_property_description_s *property)
{
int ret_key = KEY_ESC;
if (property == NULL) {
LOG_W("property is NULL\n");
return KEY_ESC;
}
item_reset();
char *title = property->name;
char *prompt = "Please set camera property";
item_reset();
const camera_spec_enums_s *enums_array = camera_spec_get_enum_array(property->id);
if (enums_array == NULL)
return KEY_ESC;
for (int i = 0; i < enums_array->count; i++) {
item_make("%d-%s",
enums_array->enums[i],
camera_string_enum_name(property->id, enums_array->enums[i]));
item_add_str("%s",
(enums_array->enums[i] == property->default_value.enum_value) ? " (default)" : "");
if (enums_array->enums[i] == property->value.enum_value) {
item_set_selected(1);
item_set_tag('X');
}
else {
item_set_selected(0);
item_set_tag(' ');
}
}
int list_height = MIN(enums_array->count + 1, 8);
ret_key = dialog_checklist(
title, prompt,
CHECKLIST_HEIGTH_MIN + list_height + 2,
WIN_COLS - CHECKLIST_WIDTH_MIN - 32,
list_height,
NULL, 0);
LOG_D("dialog_checklist() ret_key=%d\n", ret_key);
if (ret_key == KEY_ESC) {
return KEY_ESC;
} else if (ret_key == 0) {/* select */
if (!item_is_selected())
return KEY_ESC;
int enum_id = enums_array->enums[item_n()];
LOG_D("select item: pos=%d, enum=%d-%s\n",
item_n(), enum_id,
camera_string_enum_name(property->id, enum_id));
property->value.enum_value = enum_id;
return ret_key;
} else if (ret_key == 1) {/* help */
LOG_W("Help does not support yet\n");
return ret_key;
} else {
LOG_E("Unknown return value: %d\n", ret_key);
return KEY_ESC;
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_int"
#include <syslog.h>
#include <camera_manager.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
extern char dialog_input_result[MAX_LEN + 1];
int dialog_camera_property_integer(csi_camera_property_description_s *property)
{
int ret_key = KEY_ESC;
if (property == NULL) {
LOG_W("property is NULL\n");
return KEY_ESC;
}
char title[64];
snprintf(title, sizeof(title), "Camera %s setting", property->name);
char prompt[64];
snprintf(prompt, sizeof(prompt), "value range should be: [%d, %d], step %d",
property->minimum, property->maximum, property->step);
char str_value[32];
snprintf(str_value, sizeof(str_value), "%d", property->value.int_value);
again:
curs_set(1);
ret_key = dialog_inputbox(title, prompt, 10, 50, str_value);
curs_set(0);
if (ret_key == KEY_ESC || ret_key == 1)
return KEY_ESC;
/* can't be empty */
if (strlen(dialog_input_result) == 0) {
goto again;
}
/* value check, reset if invalid */
int value = atoi(dialog_input_result);
if (value < property->minimum || value > property->maximum ||
((value - property->minimum) % property->step != 0)) {
LOG_W("%s\n", prompt);
goto again;
}
/* accept value, set into property */
property->value.int_value = value;
return 0;
}

View File

@@ -0,0 +1,418 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_list"
#include <syslog.h>
#include <curses.h>
#include <camera_manager.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
#include <csi_camera_property.h>
#include <csi_camera_platform_spec.h>
extern cams_t *cam_session;
//#define USE_DUMMY_DESC
#ifdef USE_DUMMY_DESC
csi_camera_property_description_s property_hflip = {
CSI_CAMERA_PID_HFLIP, CSI_CAMERA_PROPERTY_TYPE_BOOLEAN, "horizon flip",
/*min, max , step, def, value, flag, res[2]*/
0, 1, 1, {.bool_value=true}, {.bool_value=false}, 0, {0, 0}
};
csi_camera_property_description_s property_rotate = {
CSI_CAMERA_PID_ROTATE, CSI_CAMERA_PROPERTY_TYPE_INTEGER, "rotate",
/*min, max, step, def, value, flag, res[2]*/
0, 270, 90, {.int_value=0}, {.int_value=90}, 0, {0, 0}
};
csi_camera_property_description_s property_exposure_mode = {
CSI_CAMERA_PID_EXPOSURE_MODE, CSI_CAMERA_PROPERTY_TYPE_ENUM, "exposure mode",
/*min, max, step, def, value, flag, res[2]*/
0, 0, 0, {.enum_value=CSI_CAMERA_EXPOSURE_MODE_AUTO}, {.enum_value=CSI_CAMERA_EXPOSURE_SHUTTER_PRIORITY}, 0, {0, 0}
};
csi_camera_property_description_s property_3a_lock = {
CSI_CAMERA_PID_3A_LOCK, CSI_CAMERA_PROPERTY_TYPE_BITMASK, "3A LOCK",
1, 4, 2, {.bitmask_value = 3}, {.bitmask_value = 2}, 0, {0, 0}
};
#endif
struct desc_list {
csi_camera_property_description_s desc;
struct desc_list *next;
};
struct desc_list *desc_head = NULL;
struct desc_list *desc_cur = NULL;
struct desc_list desc_nil;
static void desc_list_reset(void)
{
struct desc_list *p, *next;
for (p = desc_head; p && (p != &desc_nil); p = next) {
next = p->next;
free(p);
}
desc_head = NULL;
desc_cur = &desc_nil;
}
static void desc_list_add(csi_camera_property_description_s *desc)
{
struct desc_list *p = malloc(sizeof(*p));
memcpy(p, desc, sizeof(*desc));
if (desc_head)
desc_cur->next = p;
else
desc_head = p;
desc_cur = p;
p->next = &desc_nil;
}
static void init_camera_property_items(void)
{
#ifdef USE_DUMMY_DESC
desc_list_add(&property_hflip);
desc_list_add(&property_rotate);
desc_list_add(&property_exposure_mode);
desc_list_add(&property_3a_lock);
#else
csi_camera_property_description_s desc;
desc.id = CSI_CAMERA_PID_HFLIP;
while (!camera_query_property(cam_session, &desc)) {
//LOG_D("Get desc:%s\n", desc.name);
desc_list_add(&desc);
desc.id |= CSI_CAMERA_FLAG_NEXT_CTRL;
}
#endif
}
static void uninit_camera_property_items(void)
{
desc_list_reset();
}
static int fill_camera_property_items(void)
{
struct desc_list *node;
for (node = desc_head; node && (node != &desc_nil); node = node->next) {
csi_camera_property_description_s *desc = &(node->desc);
char item_name[64];
char item_value[64];
switch (desc->type) {
case (CSI_CAMERA_PROPERTY_TYPE_INTEGER):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "INTEGER: ");
snprintf(item_value, sizeof(item_value), "(%d)", desc->value.int_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BOOLEAN):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "BOOLEAN: ");
snprintf(item_value, sizeof(item_value), "(%s)", desc->value.bool_value ? "true" : "false");
break;
case (CSI_CAMERA_PROPERTY_TYPE_ENUM):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "ENUM: ");
snprintf(item_value, sizeof(item_value), "(%s)",
camera_string_enum_name(desc->id, desc->value.enum_value));
break;
case (CSI_CAMERA_PROPERTY_TYPE_STRING):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "STRING: ");
snprintf(item_value, sizeof(item_value), "(%s)", desc->value.str_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BITMASK):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "BITMASK: ");
snprintf(item_value, sizeof(item_value), "(%08x)", desc->value.bitmask_value);
break;
default:
LOG_E("error type!\n");
return -1;
}
item_make("%s", item_name);
item_add_str("%s --->", item_value);
item_set_data(&(node->desc));
//LOG_D("fill %s\n", desc->name);
}
return 0;
}
static int get_property_diff_count(void)
{
int diff_count = 0;
struct desc_list *node;
for (node = desc_head; node && (node != &desc_nil); node = node->next) {
//LOG_D("comparing '%s'\n", node->desc.name);
csi_camera_property_description_s desc;
desc.id = node->desc.id;
if (camera_query_property(cam_session, &desc) != 0) {
LOG_E("camera_query_property(%d), %s failed\n",
node->desc.id, node->desc.name);
continue;
}
if (memcmp(&(node->desc.value), &(desc.value), sizeof(desc.value)) == 0) {
//LOG_D("property '%s' is same\n", desc.name);
continue;
}
diff_count ++;
}
return diff_count;
}
/* return int: property count(rows) */
static int get_diff_string(char *text, int length, int rows)
{
int count = 0;
int total_len = 0;
int add_len;
text[0] = '\0';
strcat(text,"-------------------------------------------\n");
for (struct desc_list *node = desc_head;
node && (node != &desc_nil); node = node->next) {
//LOG_D("comparing '%s'\n", node->desc.name);
csi_camera_property_description_s *desc = &(node->desc);
csi_camera_property_description_s device_desc;
device_desc.id = node->desc.id;
if (camera_query_property(cam_session, &device_desc) != 0) {
LOG_E("camera_query_property(%d), %s failed\n",
node->desc.id, node->desc.name);
continue;
}
if (memcmp(&(desc->value), &(device_desc.value), sizeof(desc->value)) == 0) {
continue;
}
LOG_D("property '%s' is diff\n", desc->name);
char item_name[64];
char item_value[64];
switch (desc->type) {
case (CSI_CAMERA_PROPERTY_TYPE_INTEGER):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "INTEGER: ");
snprintf(item_value, sizeof(item_value), "(%d)", desc->value.int_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BOOLEAN):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "BOOLEAN: ");
snprintf(item_value, sizeof(item_value), "(%s)", desc->value.bool_value ? "true" : "false");
break;
case (CSI_CAMERA_PROPERTY_TYPE_ENUM):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "ENUM: ");
snprintf(item_value, sizeof(item_value), "(%s)",
camera_string_enum_name(desc->id, desc->value.enum_value));
break;
case (CSI_CAMERA_PROPERTY_TYPE_STRING):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "STRING: ");
snprintf(item_value, sizeof(item_value), "(%s)", desc->value.str_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BITMASK):
snprintf(item_name, sizeof(item_name), "%-16s:%10s", desc->name, "BITMASK: ");
snprintf(item_value, sizeof(item_value), "(%08x)", desc->value.bitmask_value);
break;
default:
LOG_E("error type!\n");
return -1;
}
if (count >= rows)
break;
add_len = strlen(item_name) + strlen(item_value) + 1;
if ((total_len + add_len) >= length) {
LOG_W("text buffer overflow\n");
break;
}
strcat(text, item_name);
strcat(text, item_value);
strcat(text, "\n");
total_len += add_len;
count++;
}
return count;
}
static int apply_property_setting(void)
{
LOG_W("do apply camera property settings\n");
int diff_count = get_property_diff_count();
int ret;
// assemble property struct
csi_camera_properties_s properties;
csi_camera_property_s *property = malloc(diff_count * sizeof(csi_camera_property_s));
properties.count = diff_count;
properties.property = property;
int i = 0;
for (struct desc_list *node = desc_head;
node && (node != &desc_nil); node = node->next) {
//LOG_D("comparing '%s'\n", node->desc.name);
csi_camera_property_description_s desc;
desc.id = node->desc.id;
if (camera_query_property(cam_session, &desc) != 0) {
LOG_E("camera_query_property(%d), %s failed\n",
node->desc.id, node->desc.name);
continue;
}
if (memcmp(&(node->desc.value), &(desc.value), sizeof(desc.value)) == 0) {
//LOG_D("property '%s' is same\n", desc.name);
continue;
}
LOG_D("property '%s' is different\n", desc.name);
property[i].id = node->desc.id;
property[i].type = node->desc.type;
memcpy(&(property[i].value), &(node->desc.value), sizeof(node->desc.value));
i++;
}
ret = camera_set_property(cam_session, &properties);
if (ret == 0)
LOG_O("camera_set_property() ok!\n");
else
LOG_E("camera_set_property() failed!\n");
free(property);
return ret;
}
int dialog_camera_property_list(void)
{
int ret_key = KEY_ESC;
int ret = 0;
csi_camera_property_description_s *init_item = NULL;
csi_camera_property_description_s *selected_item;
init_camera_property_items();
again:
item_reset();
if (fill_camera_property_items() != 0) {
LOG_E("fill_camera_property_items() failed\n");
ret = KEY_ESC;
goto exit;
}
int s_scroll = 0;
ret_key = dialog_menu("Camera Property Settings",
"Select the property, press Enter to change the property setting",
WIN_ROWS-2, WIN_COLS, init_item, -1, &s_scroll, NULL, 0);
LOG_D("dialog_menu() ret_key=%d, s_scroll=%d\n", ret_key, s_scroll);
if (ret_key == KEY_ESC) {
ret = KEY_ESC;
goto exit;
} else if (ret_key == 1) { /* Apply button */
char str_buf[1024];
int count = get_diff_string(str_buf, sizeof(str_buf), 32);
ret_key = dialog_yesno("Apply camera with new propertis below?", str_buf, 6 + count, 50);
if (ret_key != 0) { // 0 is the button position of 'yes'
LOG_D("Apply camera property is canceled\n");
goto again;
}
ret = apply_property_setting();
LOG_I("apply_property_setting() %s\n", (ret==0) ? "OK" : "Failed");
snprintf(str_buf, sizeof(str_buf),
"Apply camera properties below %s:\n",
(ret == 0) ? "OK" : "Failed");
dialog_textbox_simple("Infomation", str_buf, 10, 40);
goto exit;
} else if (ret_key == 2) { /* Cancel button */
// do nothing
ret = KEY_ESC;
goto exit;
}
/* else, Select button */
selected_item = (csi_camera_property_description_s *)item_data();
if (item_tag() == '-') {
init_item = NULL;
goto again;
}
csi_camera_property_description_s *item_property = item_data();
if (item_property == NULL) {
LOG_W("No item selected\n");
ret = KEY_ESC;
goto exit;
} else {
LOG_D("item '%s' selected\n", item_property->name);
}
switch (item_property->type) {
case CSI_CAMERA_PROPERTY_TYPE_INTEGER:
ret_key = dialog_camera_property_integer(selected_item);
if (ret != KEY_ESC) {
LOG_D("set property->value.int_value=%d\n",
selected_item->value.int_value);
}
break;
case CSI_CAMERA_PROPERTY_TYPE_BOOLEAN:
ret_key = dialog_camera_property_boolean(selected_item);
if (ret != KEY_ESC) {
LOG_D("set property.value.bool_value='%s'\n",
(selected_item->value.bool_value) ? "true" : "false");
}
break;
case CSI_CAMERA_PROPERTY_TYPE_ENUM:
ret_key = dialog_camera_property_enum(selected_item);
if (ret != KEY_ESC) {
LOG_D("set property.value.enum_value='%s'(%d)\n",
camera_string_enum_name(selected_item->id,
selected_item->value.enum_value),
selected_item->value.enum_value);
}
break;
case CSI_CAMERA_PROPERTY_TYPE_STRING:
break;
case CSI_CAMERA_PROPERTY_TYPE_BITMASK:
ret_key = dialog_camera_property_bitmask(selected_item);
if (ret != KEY_ESC) {
LOG_D("set property.value.enum_value=(%08x)\n",
selected_item->value.enum_value);
}
break;;
default:
LOG_E("Not supported property_hflip type\n");
}
init_item = item_property;
goto again;
exit:
uninit_camera_property_items();
return ret;
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_set_mode"
#include <syslog.h>
#include <camera_manager.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
int dialog_camera_set_mode(void)
{
int ret_key = KEY_ESC;
int ret;
LOG_D("Test dialog_checklist\n");
if (cam_session == NULL) {
LOG_E("cam_session is NULL\n");
return KEY_ESC;
}
if (cam_session->camera_handle == NULL) {
LOG_I("The camera has not been opened yet\n");
dialog_textbox_simple("Infomation", "There's No camera opened yet", 10, 40);
return -1;
}
again:
item_reset();
if (camera_get_modes(cam_session) != 0) {
LOG_E("camera_query_list() failed\n");
return KEY_ESC;
}
/* Prepare for checklist nodes */
csi_camera_modes_s *modes = &(cam_session->camera_modes);
for (int i = 0; i < modes->count; i++) {
char mode_desc[256];
item_make("mode-%02d: ", modes->modes[i].mode_id);
strncpy(mode_desc, modes->modes[i].description, sizeof(mode_desc));
mode_desc[60] = '\0';
item_add_str(mode_desc);
item_set_data(&modes->modes[i]); // store cam_info pointer
if (cam_session->camera_mode_id == modes->modes[i].mode_id) {
item_set_tag('X');
item_set_selected(1);
} else {
item_set_tag(' ');
item_set_selected(0);
}
}
ret = dialog_checklist(
"Set Camera mode", /* Title */
"Select the camera working mode."
"Press 'h' to get details",
CHECKLIST_HEIGTH_MIN + 10,
WIN_COLS - CHECKLIST_WIDTH_MIN - 16,
8,
NULL, 0);
int item_id;
int cam_id;
int mode_id;
int selected = item_activate_selected();
LOG_D("ret=%d, selected=%d\n", ret, selected);
char str_buf[256];
switch (ret) {
case 0: // item is selected
if (!selected)
break;
/* Set camera mode */
item_id = item_n(); // selected item: modes->modes[item_id]
cam_id = cam_session->camera_id;
mode_id = modes->modes[item_id].mode_id;
ret = camera_set_mode(cam_session, mode_id);
if (ret != 0) {
LOG_E("camera_set_mode() failed\n");
}
//char str_buf[256];
snprintf(str_buf, sizeof(str_buf),
"Set the below camera:\n"
"\t id=%d \n\t name='%s' \n\t device='%s' \n\t bus='%s'\n"
"to be working mode:%d %s",
cam_id,
cam_session->camera_infos.info[cam_id].camera_name,
cam_session->camera_infos.info[cam_id].device_name,
cam_session->camera_infos.info[cam_id].bus_info,
mode_id,
(ret == 0) ? "OK" : "Failed");
dialog_textbox_simple("Infomation", str_buf, 10, 40);
LOG_I("csi_camera_infos_s.info[%d] is opened %s\n",
cam_id, (ret == 0) ? "OK" : "Failed");
cam_session->camera_mode_id = mode_id;
/* Show message bar */
snprintf(str_buf, sizeof(str_buf),
"Set camera(%d) to be mode: %d %s\n",
cam_id, mode_id, (ret == 0) ? "OK" : "Failed");
message(str_buf, (ret == 0) ? 1 : 2);
break;
case 1: // need help
cam_id = item_n();
//char str_buf[256];
snprintf(str_buf, sizeof(str_buf),
"Camera info:\n"
"\t id=%d \n\t name='%s' \n\t device='%s' \n\t bus='%s'\n",
cam_id,
cam_session->camera_infos.info[cam_id].camera_name,
cam_session->camera_infos.info[cam_id].device_name,
cam_session->camera_infos.info[cam_id].bus_info);
dialog_textbox_simple("Infomation", str_buf, 10, 40);
goto again;
case KEY_ESC: // specific KEY
break;
case -ERRDISPLAYTOOSMALL: // error
default:
LOG_W("Oops? why return ret=%d\n", ret);
break;
}
LOG_D("dialog_checklist() ret=%d\n", ret);
return 0;
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_chn_list"
#include <syslog.h>
#include <curses.h>
#include <camera_manager.h>
#include <camera_string.h>
#include "app_dialogs.h"
extern cams_t *cam_session;
int dialog_channel_list(void)
{
int ret_key = KEY_ESC;
int ret;
if (cam_session == NULL) {
LOG_E("cam_session is NULL\n");
return KEY_ESC;
}
/* Get camera list */
if (camera_channel_query_list(cam_session) != 0) {
LOG_E("camera_get_list() failed\n");
return KEY_ESC;
}
char title[64];
snprintf(title, sizeof(title), "Camera[%d] Channels List", cam_session->camera_id);
char text[256*CSI_CAMERA_CHANNEL_MAX_COUNT] = "";
char item[256];
char temp[128];
int valid_count = 0;
for (int i = CSI_CAMERA_CHANNEL_0; i < CSI_CAMERA_CHANNEL_MAX_COUNT; i++) {
csi_camera_channel_cfg_s *chn_cfg = &(cam_session->chn_cfg[i]);
if (chn_cfg->status == CSI_CAMERA_CHANNEL_INVALID)
continue;
if (valid_count > 0)
strcat(text, "\n");
snprintf(item, sizeof(item), "Channel[%d] info:\n", chn_cfg->chn_id);
strcat(text, item);
snprintf(item, sizeof(item), "\t Status : %s\n",
camera_string_chn_status(chn_cfg->status));
strcat(text, item);
snprintf(item, sizeof(item), "\t Capture: %s\n",
camera_string_chn_capture_types(chn_cfg->capture_type, temp));
strcat(text, item);
snprintf(item, sizeof(item), "\t Frame : count=%d, type=%s\n",
chn_cfg->frm_cnt, camera_string_img_type(chn_cfg->img_type));
strcat(text, item);
snprintf(item, sizeof(item), "\t Image : width=%d, height=%d, pix_fmt=%s\n",
chn_cfg->img_fmt.width, chn_cfg->img_fmt.height,
camera_string_pixel_format(chn_cfg->img_fmt.pix_fmt));
strcat(text, item);
snprintf(item, sizeof(item), "\t Meta : %s\n",
camera_string_chn_meta_fields(chn_cfg->meta_fields, temp));
strcat(text, item);
valid_count++;
}
int height = MIN((valid_count * 7 + 4), (WIN_ROWS - 6));
return dialog_textbox_simple(title, text, height, 80);
}

View File

@@ -0,0 +1,573 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_list"
#include <syslog.h>
#include <csi_camera_property.h>
#include <csi_camera_platform_spec.h>
#include <camera_manager.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
static int fill_channel_config_items(csi_camera_channel_cfg_s *channel)
{
char str_buf[128];
const char item_format[] = "%-14s";
item_make(item_format, "capture_type");
item_add_str(": (%s) --->", camera_string_chn_capture_types(channel->capture_type, str_buf));
item_set_data(channel);
item_make(item_format, "Capture fields");
item_add_str(": (%s) --->", camera_string_chn_meta_fields(channel->meta_fields, str_buf));
item_set_data(channel);
item_make(item_format, "Buffer count");
item_add_str(": (%d) --->", channel->frm_cnt);
item_set_data(channel);
item_make(item_format, "Image width");
item_add_str(": (%d) --->", channel->img_fmt.width);
item_set_data(channel);
item_make(item_format, "Image height");
item_add_str(": (%d) --->", channel->img_fmt.height);
item_set_data(channel);
item_make(item_format, "Pixel format");
item_add_str(": (%s) --->", camera_string_pixel_format(channel->img_fmt.pix_fmt));
item_set_data(channel);
item_make(item_format, "Buffer type");
item_add_str(": (%s) --->", camera_string_img_type(channel->img_type));
item_set_data(channel);
return 0;
}
typedef enum channel_param {
CHANNEL_PARAM_CAPTURE_TYPE = 0,
CHANNEL_PARAM_META_FIELDS,
CHANNEL_PARAM_FRM_CNT,
CHANNEL_PARAM_IMG_WIDTH,
CHANNEL_PARAM_IMG_HEIGIT,
CHANNEL_PARAM_IMG_PIX_FMT,
CHANNEL_PARAM_IMG_TYPE,
} channel_param_e;
extern char dialog_input_result[MAX_LEN + 1];
static int channel_config_integer(csi_camera_channel_cfg_s *channel, channel_param_e param)
{
int ret_key = KEY_ESC;
char title[64];
char prompt[64] = "Please enter the appropriate number";
char str_value[32];
if (channel == NULL) {
LOG_W("channel is NULL\n");
return KEY_ESC;
}
again:
switch (param) {
case CHANNEL_PARAM_FRM_CNT:
snprintf(title, sizeof(title), "Config Channel[%d] %s",
channel->chn_id, "Buffer Count");
snprintf(str_value, sizeof(str_value), "%d", channel->frm_cnt);
break;
case CHANNEL_PARAM_IMG_WIDTH:
snprintf(title, sizeof(title), "Config Channel[%d] %s",
channel->chn_id, "Image Width");
snprintf(str_value, sizeof(str_value), "%d", channel->img_fmt.width);
break;
case CHANNEL_PARAM_IMG_HEIGIT:
snprintf(title, sizeof(title), "Config Channel[%d] %s",
channel->chn_id, "Image Height");
snprintf(str_value, sizeof(str_value), "%d", channel->img_fmt.height);
break;
default:
break;
}
curs_set(1);
ret_key = dialog_inputbox(title, prompt, 9, 40, str_value);
curs_set(0);
if (ret_key == KEY_ESC || ret_key == 1)
return KEY_ESC;
/* can't be empty */
if (strlen(dialog_input_result) == 0) {
goto again;
}
/* value check, reset if invalid */
int value = atoi(dialog_input_result);
if (value <= 0){
goto again;
}
/* accept value, set into property */
switch (param) {
case CHANNEL_PARAM_FRM_CNT:
if (value > 100){ // filt unreasonable out
goto again;
}
channel->frm_cnt = value;
break;
case CHANNEL_PARAM_IMG_WIDTH:
if (value > (7680*2)){ // filt unreasonable out
goto again;
}
channel->img_fmt.width = value;
break;
case CHANNEL_PARAM_IMG_HEIGIT:
if (value > (4320*2)){ // filt unreasonable out
goto again;
}
channel->img_fmt.height = value;
break;
default:
break;
}
return 0;
}
static int channel_config_enum(csi_camera_channel_cfg_s *channel, channel_param_e param)
{
int ret_key = KEY_ESC;
char title[64];
char prompt[64] = "Please select the appropriate enum item";
char str_value[32];
const camera_spec_enums_s *enums_array;
if (channel == NULL) {
LOG_W("channel is NULL\n");
return KEY_ESC;
}
item_reset();
switch (param) {
case CHANNEL_PARAM_IMG_PIX_FMT:
snprintf(title, sizeof(title), "Config Channel[%d] %s",
channel->chn_id, "Image Pixel Format");
enums_array = camera_spec_get_enum_array(CAMERA_SPEC_ENUM_CHANNEL_PIX_FMT);
if (enums_array == NULL) {
LOG_E("No enum array for CAMERA_SPEC_ENUM_CHN_PIX_FMT(%d)\n",
CAMERA_SPEC_ENUM_CHANNEL_PIX_FMT);
return KEY_ESC;
}
for (int i = 0; i < enums_array->count; i++) {
item_make("%d-%s", enums_array->enums[i],
camera_string_pixel_format(enums_array->enums[i]));
//item_add_str("");
if (channel->img_fmt.pix_fmt == enums_array->enums[i]) {
item_set_selected(1);
item_set_tag('X');
} else {
item_set_selected(0);
item_set_tag(' ');
}
}
break;
case CHANNEL_PARAM_IMG_TYPE:
snprintf(title, sizeof(title), "Config Channel[%d] %s",
channel->chn_id, "Image Buffer Type");
enums_array = camera_spec_get_enum_array(CAMERA_SPEC_ENUM_CHANNEL_IMG_TYPE);
if (enums_array == NULL) {
LOG_E("No enum array for CAMERA_SPEC_ENUM_CHN_IMG_TYPE(%08x)\n",
CAMERA_SPEC_ENUM_CHANNEL_IMG_TYPE);
return KEY_ESC;
}
for (int i = 0; i < enums_array->count; i++) {
item_make("%d-%s", i, camera_string_img_type(i));
//item_add_str("");
if (channel->img_type == enums_array->enums[i]) {
item_set_selected(1);
item_set_tag('X');
} else {
item_set_selected(0);
item_set_tag(' ');
}
}
break;
default:
return KEY_ESC;
}
int list_height = MIN(enums_array->count + 1, 8);
ret_key = dialog_checklist(
title, prompt,
CHECKLIST_HEIGTH_MIN + list_height + 2,
WIN_COLS - CHECKLIST_WIDTH_MIN - 32,
list_height,
NULL, 0);
LOG_D("dialog_checklist() ret_key=%d\n", ret_key);
if (ret_key == KEY_ESC) {
return KEY_ESC;
} else if (ret_key == 0) { /* select */
if (!item_is_selected())
return KEY_ESC;
int enum_id = enums_array->enums[item_n()];
switch(param) {
case CHANNEL_PARAM_IMG_PIX_FMT:
LOG_D("select item: pos=%d, enum=%d:%s\n",
item_n(), enum_id, camera_string_pixel_format(enum_id));
channel->img_fmt.pix_fmt = enum_id;
break;
case CHANNEL_PARAM_IMG_TYPE:
LOG_D("select item: pos=%d, enum=%d:%s\n",
item_n(), enum_id, camera_string_img_type(enum_id));
channel->img_type = enum_id;
break;
default:
return KEY_ESC;
}
return ret_key;
} else if (ret_key == 1) { /* help */
LOG_W("Help does not support yet\n");
return ret_key;
} else {
LOG_E("Unknown return value: %d\n", ret_key);
return KEY_ESC;
}
return 0;
}
static int channel_config_bitmsk_capture_type(csi_camera_channel_cfg_s *channel)
{
int ret_key = KEY_ESC;
if (channel == NULL) {
LOG_W("channel is NULL\n");
return KEY_ESC;
}
char title[64];
char prompt[64] = "Please select the appropriate enum item";
int item_pos = 0;
snprintf(title, sizeof(title), "Config Channel[%d] Capture Types", channel->chn_id);
const camera_spec_bitmasks_t *bitmasks_array =
camera_spec_get_bitmask_array(CAMERA_SPEC_BITMAKS_CHANNEL_CAPTURE_TYPE);
if (bitmasks_array == NULL)
return KEY_ESC;
again:
item_reset();
for (int i = 0; i < bitmasks_array->count; i++) {
item_make("bit-%02d: %s", bitmasks_array->bitmask[i],
camera_string_capture_type(bitmasks_array->bitmask[i], true));
//item_add_str("");
if (bitmasks_array->bitmask[i] & channel->capture_type) {
item_set_selected(1);
item_set_tag('*');
}
else {
item_set_selected(0);
item_set_tag(' ');
}
}
int list_height = MIN(bitmasks_array->count + 1, 8);
ret_key = dialog_checkbox(
title, prompt,
CHECKLIST_HEIGTH_MIN + list_height + 2,
WIN_COLS - CHECKLIST_WIDTH_MIN - 32,
list_height, item_pos);
LOG_D("dialog_checkbox() ret_key=%d\n", ret_key);
if (ret_key == KEY_ESC) {
return KEY_ESC;
} else if (ret_key == 0) {/* select */
item_pos = item_n();
int bitmask_value = bitmasks_array->bitmask[item_n()];
if (item_is_selected()) {
channel->capture_type |= bitmask_value;
} else {
channel->capture_type &= ~bitmask_value;
}
int enum_id = bitmasks_array->bitmask[item_n()];
LOG_D("%s item: pos=%d, enum=%d-%s, bitmask_value=%08x\n",
item_is_selected() ? "Select" : "Unselect",
item_n(), enum_id,
camera_string_capture_type(enum_id, true),
channel->capture_type);
goto again;
return ret_key;
} else if (ret_key == 1) {/* help */
LOG_W("Help does not support yet\n");
return ret_key;
} else {
LOG_E("Unknown return value: %d\n", ret_key);
return KEY_ESC;
}
}
static int channel_config_bitmsk_meta_type(csi_camera_channel_cfg_s *channel)
{
int ret_key = KEY_ESC;
if (channel == NULL) {
LOG_W("channel is NULL\n");
return KEY_ESC;
}
char title[64];
char prompt[64] = "Please select the appropriate enum item";
int item_pos = 0;
snprintf(title, sizeof(title), "Config Channel[%d] Meta Types", channel->chn_id);
const camera_spec_bitmasks_t *bitmasks_array =
camera_spec_get_bitmask_array(CAMERA_SPEC_BITMAKS_CHANNEL_META_TYPE);
if (bitmasks_array == NULL)
return KEY_ESC;
again:
item_reset();
for (int i = 0; i < bitmasks_array->count; i++) {
item_make("bit-%02d: %s", bitmasks_array->bitmask[i],
camera_string_meta_field(bitmasks_array->bitmask[i], true));
//item_add_str("");
if (bitmasks_array->bitmask[i] & channel->meta_fields) {
item_set_selected(1);
item_set_tag('*');
}
else {
item_set_selected(0);
item_set_tag(' ');
}
}
int list_height = MIN(bitmasks_array->count + 1, 8);
ret_key = dialog_checkbox(
title, prompt,
CHECKLIST_HEIGTH_MIN + list_height + 2,
WIN_COLS - CHECKLIST_WIDTH_MIN - 32,
list_height, item_pos);
LOG_D("dialog_checkbox() ret_key=%d\n", ret_key);
if (ret_key == KEY_ESC) {
return KEY_ESC;
} else if (ret_key == 0) {/* select */
item_pos = item_n();
int bitmask_value = bitmasks_array->bitmask[item_n()];
if (item_is_selected()) {
channel->meta_fields |= bitmask_value;
} else {
channel->meta_fields &= ~bitmask_value;
}
int enum_id = bitmasks_array->bitmask[item_n()];
LOG_D("%s item: pos=%d, enum=%d-%s, bitmask_value=%08x\n",
item_is_selected() ? "Select" : "Unselect",
item_n(), enum_id,
camera_string_meta_field(enum_id, true),
channel->meta_fields);
goto again;
return ret_key;
} else if (ret_key == 1) {/* help */
LOG_W("Help does not support yet\n");
return ret_key;
} else {
LOG_E("Unknown return value: %d\n", ret_key);
return KEY_ESC;
}
}
/* return int: property rows */
static int get_diff_string(char *text, csi_camera_channel_cfg_s *channel)
{
int count = 0;
int total_len = 0;
int add_len;
text[0] = '\0';
strcat(text,"-------------------------------------------\n");
char item_name[64];
char item_value[256];
char str_buf1[128];
char str_buf2[128];
if(cam_session->chn_cfg_tmp.capture_type != channel->capture_type) {
snprintf(item_name, sizeof(item_name), "%-14s", "capture type");
snprintf(item_value, sizeof(item_value), ": (%s) => (%s)\n",
camera_string_chn_capture_types(channel->capture_type, str_buf1),
camera_string_chn_capture_types(cam_session->chn_cfg_tmp.capture_type, str_buf2));
strcat(text, item_name);
strcat(text, item_value);
count++;
}
if(cam_session->chn_cfg_tmp.meta_fields != channel->meta_fields) {
snprintf(item_name, sizeof(item_name), "%-14s", "Meta fields");
snprintf(item_value, sizeof(item_value), ": (%s) =>\n\t\t (%s)\n",
camera_string_chn_meta_fields(channel->meta_fields, str_buf1),
camera_string_chn_meta_fields(cam_session->chn_cfg_tmp.meta_fields, str_buf2));
strcat(text, item_name);
strcat(text, item_value);
count+=2;
}
if(cam_session->chn_cfg_tmp.frm_cnt != channel->frm_cnt) {
snprintf(item_name, sizeof(item_name), "%-14s", "buffer count");
snprintf(item_value, sizeof(item_value), ": (%d) => (%d)\n",
channel->frm_cnt, cam_session->chn_cfg_tmp.frm_cnt);
strcat(text, item_name);
strcat(text, item_value);
count++;
}
if(cam_session->chn_cfg_tmp.img_fmt.width != channel->img_fmt.width) {
snprintf(item_name, sizeof(item_name), "%-14s", "Image width");
snprintf(item_value, sizeof(item_value), ": (%d) => (%d)\n",
channel->img_fmt.width, cam_session->chn_cfg_tmp.img_fmt.width);
strcat(text, item_name);
strcat(text, item_value);
count++;
}
if(cam_session->chn_cfg_tmp.img_fmt.height != channel->img_fmt.height) {
snprintf(item_name, sizeof(item_name), "%-14s", "Image height");
snprintf(item_value, sizeof(item_value), ": (%d) => (%d)\n",
channel->img_fmt.height, cam_session->chn_cfg_tmp.img_fmt.height);
strcat(text, item_name);
strcat(text, item_value);
count++;
}
if(cam_session->chn_cfg_tmp.img_fmt.pix_fmt != channel->img_fmt.pix_fmt) {
snprintf(item_name, sizeof(item_name), "%-14s", "Pixel format");
snprintf(item_value, sizeof(item_value), ": (%s) => (%s)\n",
camera_string_pixel_format(channel->img_fmt.pix_fmt),
camera_string_pixel_format(cam_session->chn_cfg_tmp.img_fmt.pix_fmt));
strcat(text, item_name);
strcat(text, item_value);
count++;
}
if(cam_session->chn_cfg_tmp.img_type != channel->img_type) {
snprintf(item_name, sizeof(item_name), "%-14s", "Buffer type");
snprintf(item_value, sizeof(item_value), ": (%s) => (%s)\n",
camera_string_img_type(channel->img_type),
camera_string_img_type(cam_session->chn_cfg_tmp.img_type));
strcat(text, item_name);
strcat(text, item_value);
count++;
}
return count;
}
static int channel_open_internal(char *feedback)
{
int ret = camera_channel_open(cam_session, &cam_session->chn_cfg_tmp);
if (ret != 0) {
LOG_E("camera_channel_open() failed, ret=%d\n", ret);
}
if (feedback) {
if (ret)
sprintf(feedback, "camera_channel_open() failed, ret=%d\n", ret);
else
sprintf(feedback, "camera_channel_open() OK\n");
}
return ret;
}
int dialog_channel_open(csi_camera_channel_cfg_s *channel)
{
int ret_key = KEY_ESC;
int ret = 0;
char str_buf[1024];
int item_pos = 0;
csi_camera_channel_cfg_s *chn_tmp = &(cam_session->chn_cfg_tmp);
memcpy(chn_tmp, channel, sizeof(*chn_tmp));
again:
item_reset();
if (fill_channel_config_items(chn_tmp) != 0) {
LOG_E("fill_channel_config_items() failed\n");
ret = KEY_ESC;
goto exit;
}
char *button_names[] = {"Config", " Open ", "Cancel"};
int s_scroll = 0;
snprintf(str_buf, sizeof(str_buf), "Config Camera[%d] - Channel[%d]",
cam_session->camera_id, chn_tmp->chn_id);
ret_key = dialog_menu(str_buf, "Select item, press Enter to config",
WIN_ROWS-2, WIN_COLS, NULL, item_pos, &s_scroll, button_names, 3);
item_pos = item_activate_selected_pos();
LOG_D("dialog_menu() ret_key=%d, item_pos=%d\n", ret_key, item_pos);
if (ret_key == 0) { /* Select button */
if (item_pos == CHANNEL_PARAM_FRM_CNT ||
item_pos == CHANNEL_PARAM_IMG_WIDTH ||
item_pos == CHANNEL_PARAM_IMG_HEIGIT) {
channel_config_integer(chn_tmp, item_pos);
} else if (item_pos == CHANNEL_PARAM_IMG_PIX_FMT ||
item_pos == CHANNEL_PARAM_IMG_TYPE) {
channel_config_enum(chn_tmp, item_pos);
} else if (item_pos == CHANNEL_PARAM_CAPTURE_TYPE) {
channel_config_bitmsk_capture_type(chn_tmp);
} else if (item_pos == CHANNEL_PARAM_META_FIELDS){
channel_config_bitmsk_meta_type(chn_tmp);
}
goto again;
} else if (ret_key == 1) { /* Open button */
ret = channel_open_internal(str_buf);
LOG_I("%s\n", str_buf);
dialog_textbox_simple("Infomation", str_buf, 10, 40);
if (ret != 0) {
goto again;
}
goto exit;
} else if (ret_key == 2) { /* Cancel button */
// do nothing
ret = KEY_ESC;
goto exit;
} else {
ret = KEY_ESC;
goto exit;
}
/* else, Select button */
goto again;
exit:
return ret;
}

View File

@@ -0,0 +1,339 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_chn_run"
#include <syslog.h>
#include <camera_manager.h>
#include <camera_string.h>
#include "param.h"
#include "platform_action.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
#define _CHECK_SESSION_RETURN() \
do { \
if (session == NULL) { \
LOG_E("session is NULL\n"); \
return -EPERM; \
} \
} while (0)
static int do_camera_event_action(cams_t *session, csi_camera_event_s *event)
{
_CHECK_SESSION_RETURN();
int ret = 0;
for (uint32_t i = 0; i < CSI_CAMERA_EVENT_MAX_COUNT; i++) {
camera_event_action_t *event_action =
&(session->camera_event_action[i].camera);
if (event_action->event != event->id)
continue;
LOG_D("Found camera action:%s\n",
camera_string_camera_action(event_action->action));
if(event_action->action == CAMERA_ACTION_NONE) {
LOG_D("CHANNEL CAMERA_ACTION_NONE!\n");
continue;
}
if(event_action->action > (CAMERA_ACTION_LOG_PRINT|CAMERA_ACTION_CAPTURE_FRAME)) {
LOG_E("Unkonw camera event action: %d\n", event_action->action);
ret = -1;
}
for(uint32_t j = 0; j < CAMERA_ACTION_MAX_COUNT; j++) {
switch (event_action->action & 1 << j) {
case CAMERA_ACTION_LOG_PRINT:
LOG_D("CAMERA CAMERA_ACTION_LOG_PRINT\n");
if((event_action->event & 1 << i) == CSI_CAMERA_EVENT_WARNING) {
LOG_D("LOG_PRINT CSI_CAMERA_EVENT_WARNING\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_EVENT_ERROR) {
LOG_D("LOG PRINT CSI_CAMERA_EVENT_ERROR\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_EVENT_SENSOR_FIRST_IMAGE_ARRIVE) {
LOG_D("LOG PRINT CSI_CAMERA_EVENT_SENSOR_FIRST_IMAGE_ARRIVE\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_EVENT_ISP_3A_ADJUST_READY) {
LOG_D("LOG PRINT CSI_CAMERA_EVENT_ISP_3A_ADJUST_READY\n");
} else {
ret = -1;
LOG_E("CAMERA CAMERA_ACTION_LOG_ERROR\n");
}
break;
case CAMERA_ACTION_CAPTURE_FRAME:
LOG_D("CAMERA CAMERA_ACTION_CAPTURE_FRAME\n");
if((event_action->event & 1 << i) == CSI_CAMERA_EVENT_WARNING) {
LOG_D("CAPTURE FRAME CSI_CAMERA_EVENT_WARNING\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_EVENT_ERROR) {
LOG_D("CAPTURE FRAME CSI_CAMERA_EVENT_ERROR\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_EVENT_SENSOR_FIRST_IMAGE_ARRIVE) {
LOG_D("CAPTURE FRAME CSI_CAMERA_EVENT_SENSOR_FIRST_IMAGE_ARRIVE\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_EVENT_ISP_3A_ADJUST_READY) {
LOG_D("CAPTURE FRAME CSI_CAMERA_EVENT_ISP_3A_ADJUST_READY\n");
} else {
ret = -1;
LOG_D("CAMERA CAMERA_ACTION_CAPTURE_FRAME_ERROR\n");
}
break;
default:
break;
}
}
}
return 0;
}
static int do_channel_event_action(cams_t *session, csi_camera_event_s *event)
{
_CHECK_SESSION_RETURN();
csi_frame_s frame;
int ret = 0;
camera_event_action_union_t *event_action_u =
session->channel_event_action[event->type - CSI_CAMERA_EVENT_TYPE_CHANNEL0];
LOG_D("do_channel_event_action()!\n");
for (uint32_t i = 0; i < CSI_CAMERA_CHANNEL_EVENT_MAX_COUNT; i++) {
camera_channel_event_action_t *event_action = &(event_action_u[i].channel);
if (event_action->event != event->id)
continue;
if (event_action->action == 0) {
printf("event_action->action == 0\n");
break;
}
LOG_D("Found channel action:%s\n",
camera_string_channel_action(event_action->action));
if(event_action->action == CAMERA_CHANNEL_ACTION_NONE) {
LOG_D("CHANNEL CAMERA_ACTION_NONE!\n");
continue;
}
if(event_action->action > (CAMERA_CHANNEL_ACTION_LOG_PRINT|CAMERA_CHANNEL_ACTION_CAPTURE_FRAME|CAMERA_CHANNEL_ACTION_DISPLAY_FRAME)) {
ret = -1;
LOG_E("Unkonw channel event action: %d\n", event_action->action);
}
for(uint32_t j = 0; j < CAMERA_CHANNEL_ACTION_MAX_COUNT; j++) {
switch (event_action->action & 1 << j) {
case CAMERA_CHANNEL_ACTION_LOG_PRINT:
LOG_D("CHANNEL CAMERA_ACTION_LOG_PRINT\n");
if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_FRAME_READY) {
LOG_D("LOG_PRINT CSI_CAMERA_CHANNEL_EVENT_FRAME_READY\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_FRAME_PUT) {
LOG_D("LOG_PRINT CSI_CAMERA_CHANNEL_EVENT_FRAME_PUT\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_OVERFLOW) {
LOG_D("LOG_PRINT CSI_CAMERA_CHANNEL_EVENT_OVERFLOW\n");
} else {
ret = -1;
LOG_E("CHANNEL CAMERA_ACTION_LOG_ERROR\n");
}
break;
case CAMERA_CHANNEL_ACTION_CAPTURE_FRAME:
LOG_D("CHANNEL CAMERA_ACTION_CAPTURE_FRAME\n");
/* To show the image can do below steps:
* 1. save capture img to be /tmp/capture.jpg
* 2. img2txt -W 80 -H 60 -f ansi /tmp/capture.jpg > /tmp/capture.txt
* 3. malloc a img_buf and store /tmp/capture.txt into it
* 4. printf(img_buf) to show on log console screen
*/
if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_FRAME_READY) {
int timeout = -1;
int read_frame_count = csi_camera_get_frame_count(NULL, event->type - CSI_CAMERA_EVENT_TYPE_CHANNEL0);
LOG_D("read_frame_count = %d\n",read_frame_count);
for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(NULL,event->type - CSI_CAMERA_EVENT_TYPE_CHANNEL0, &frame, timeout);
if(frame.img.usr_addr[0] != NULL) {
camera_action_image_save(&frame);
csi_camera_put_frame(&frame);
}
}
} else if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_FRAME_PUT) {
LOG_D("CSI_CAMERA_CHANNEL_EVENT_FRAME_PUT\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_OVERFLOW) {
LOG_D("CSI_CAMERA_CHANNEL_EVENT_OVERFLOW\n");
} else {
ret = -1;
LOG_E("CHANNEL CAMERA_ACTION_CAPTURE_FRAME_ERROR\n");
}
break;
case CAMERA_CHANNEL_ACTION_DISPLAY_FRAME:
LOG_D("CHANNEL CAMERA_ACTION_DISPLAY_FRAME");
if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_FRAME_READY) {
int timeout = -1;
int read_frame_count = csi_camera_get_frame_count(NULL, event->type - CSI_CAMERA_EVENT_TYPE_CHANNEL0);
LOG_D("read_frame_count = %d\n",read_frame_count);
//for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(NULL,event->type - CSI_CAMERA_EVENT_TYPE_CHANNEL0, &frame, timeout);
if(frame.img.usr_addr[0] != NULL) {
camera_action_image_display(&frame);
LOG_D("frame->usr_addr = %p\n",frame.img.usr_addr[0]);
csi_camera_put_frame(&frame);
}
//}
} else if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_FRAME_PUT) {
LOG_D("CSI_CAMERA_CHANNEL_EVENT_FRAME_PUT\n");
} else if((event_action->event & 1 << i) == CSI_CAMERA_CHANNEL_EVENT_OVERFLOW) {
LOG_D("CSI_CAMERA_CHANNEL_EVENT_OVERFLOW\n");
} else {
ret = -1;
LOG_E("CHANNEL CAMERA_ACTION_DISPLAY_FRAME_ERROR\n");
}
break;
default:
break;
}
}
}
return ret;
}
/* action: 0:close, 1:open, 2:start/stop */
int dialog_channel_run(void)
{
int ret_key = KEY_ESC;
int ret;
char str_buf[256];
csi_camera_channel_cfg_s *selected_chn = NULL;
if (cam_session == NULL) {
LOG_E("cam_session is NULL\n");
return KEY_ESC;
}
if (cam_session->camera_handle == NULL) {
csi_camera_info_s *info =
&(cam_session->camera_infos.info[cam_session->camera_id]);
snprintf(str_buf, sizeof(str_buf),
"Please open camera first\n");
dialog_textbox_simple("Error", str_buf, 6, 30);
return KEY_ESC;
}
again:
item_reset();
if (camera_channel_query_list(cam_session) != 0) {
LOG_E("camera_channel_query_list() failed\n");
snprintf(str_buf, sizeof(str_buf),
"Failed to query channel list from Camera failed!\n");
dialog_textbox_simple("Error", str_buf, 10, 40);
return KEY_ESC;
}
/* Prepare for checklist nodes */
for (int i = CSI_CAMERA_CHANNEL_0; i < CSI_CAMERA_CHANNEL_MAX_COUNT; i++) {
csi_camera_channel_cfg_s *channel = &(cam_session->chn_cfg[i]);
if (channel->status == CSI_CAMERA_CHANNEL_INVALID) {
continue;
}
item_make("Channel[%d]", channel->chn_id);
item_add_str(" (%s)", camera_string_chn_status(channel->status));
item_set_data(channel);
if (channel->status == CSI_CAMERA_CHANNEL_RUNNING || channel->status == CSI_CAMERA_CHANNEL_OPENED) {
item_set_tag('X');
item_set_selected(1);
}
}
char *button_names[] = {"Start", "Stop", "Cancel"};
ret = dialog_checklist(
"Start/Stop Channel", /* Title */
"Select the channel to start or stop",
CHECKLIST_HEIGTH_MIN + 10,
WIN_COLS - CHECKLIST_WIDTH_MIN - 16, 8,
button_names, ARRAY_SIZE(button_names));
int selected = item_activate_selected();
LOG_D("ret=%d, selected=%s\n", ret, selected ? "true" : "false");
switch (ret) {
case 0: // button is: start
if (!selected || item_data() == NULL)
break;
/* Show operation result */
selected_chn = (csi_camera_channel_cfg_s *)item_data();
if (selected_chn->status != CSI_CAMERA_CHANNEL_OPENED) {
/* Show message bar */
snprintf(str_buf, sizeof(str_buf),
"The Camera[%d] channel[%d] can't start, current status is '%s'\n",
cam_session->camera_id, selected_chn->chn_id,
camera_string_chn_status(selected_chn->status));
message(str_buf, 2);
goto again;
}
camera_register_event_action(cam_session,
do_camera_event_action,
do_channel_event_action);
LOG_D("camera_channel_start selected_chn->chn_id = %x\n",selected_chn->chn_id);
ret = camera_channel_start(cam_session, selected_chn->chn_id);
/* Show message bar */
snprintf(str_buf, sizeof(str_buf),
"Start Camera[%d] channel[%d] %s\n",
cam_session->camera_id, selected_chn->chn_id,
(ret == 0) ? "OK" : "failed");
message(str_buf, (ret == 0) ? 1 : 2);
goto again;
break;
case 1: // button is: stop
if (!selected || item_data() == NULL)
break;
/* Show operation result */
selected_chn = (csi_camera_channel_cfg_s *)item_data();
if (selected_chn->status != CSI_CAMERA_CHANNEL_RUNNING) {
/* Show message bar */
snprintf(str_buf, sizeof(str_buf),
"The Camera[%d] channel[%d] can't stop, current status is '%s'\n",
cam_session->camera_id, selected_chn->chn_id,
camera_string_chn_status(selected_chn->status));
message(str_buf, 2);
goto again;
}
ret = camera_channel_stop(cam_session, selected_chn->chn_id);
/* Show message bar */
snprintf(str_buf, sizeof(str_buf),
"Stop Camera[%d] channel[%d] %s\n",
cam_session->camera_id, selected_chn->chn_id,
(ret == 0) ? "OK" : "failed");
message(str_buf, (ret == 0) ? 1 : 2);
goto again;
break;
case 2: // button is: cancel
case KEY_ESC: // specific KEY
ret = KEY_ESC;
break;
default:
LOG_W("Oops? why return ret=%d\n", ret);
ret = KEY_ESC;
break;
}
LOG_D("ret=%d\n", ret);
return ret;
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_chn_select"
#include <syslog.h>
#include <camera_manager.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
/* action: 0:close, 1:open, 2:start/stop */
int dialog_channel_select(csi_camera_channel_cfg_s **selected_chn, int action)
{
int ret_key = KEY_ESC;
int ret;
char str_buf[256];
*selected_chn = NULL;
if (cam_session == NULL) {
LOG_E("cam_session is NULL\n");
return KEY_ESC;
}
if (cam_session->camera_handle == NULL) {
csi_camera_info_s *info =
&(cam_session->camera_infos.info[cam_session->camera_id]);
snprintf(str_buf, sizeof(str_buf),
"Please open camera first\n");
dialog_textbox_simple("Error", str_buf, 6, 30);
return KEY_ESC;
}
again:
item_reset();
if (camera_channel_query_list(cam_session) != 0) {
LOG_E("camera_channel_query_list() failed\n");
snprintf(str_buf, sizeof(str_buf),
"Failed to query channel list from Camera failed!\n");
dialog_textbox_simple("Error", str_buf, 10, 40);
return KEY_ESC;
}
/* Prepare for checklist nodes */
for (int i = CSI_CAMERA_CHANNEL_0; i < CSI_CAMERA_CHANNEL_MAX_COUNT; i++) {
csi_camera_channel_cfg_s *chn_cfg = &(cam_session->chn_cfg[i]);
if (chn_cfg->status == CSI_CAMERA_CHANNEL_INVALID) {
continue;
}
item_make("Channel[%d]", chn_cfg->chn_id);
item_add_str(" (%s) --->", camera_string_chn_status(chn_cfg->status));
item_set_data(chn_cfg);
if (chn_cfg->status == CSI_CAMERA_CHANNEL_OPENED || chn_cfg->status == CSI_CAMERA_CHANNEL_RUNNING) {
item_set_tag('X');
item_set_selected(1);
}
}
if (action == 0) { // action is close
char *button_names[] = {" Close ", " Help "};
ret = dialog_checklist(
"Select Channel", /* Title */
"Select the channel to close",
CHECKLIST_HEIGTH_MIN + 10,
WIN_COLS - CHECKLIST_WIDTH_MIN - 16, 8,
button_names, sizeof(button_names) / sizeof(button_names[0]));
} else if (action == 1) { // action is open
ret = dialog_checklist(
"Select Channel", /* Title */
"Select the channel to config and open",
CHECKLIST_HEIGTH_MIN + 10,
WIN_COLS - CHECKLIST_WIDTH_MIN - 16, 8,
NULL, 0);
} else { // action is start/stop
ret = dialog_checklist(
"Select Channel", /* Title */
"Select the channel to Start or Stop",
CHECKLIST_HEIGTH_MIN + 10,
WIN_COLS - CHECKLIST_WIDTH_MIN - 16, 8,
NULL, 0);
}
int selected = item_activate_selected();
LOG_D("ret=%d, selected=%s\n", ret, selected ? "true" : "false");
switch (ret) {
case 0: // item is selected/close
if (!selected)
break;
/* Show operation result */
*selected_chn = (csi_camera_channel_cfg_s *)item_data();
if (action == 0) { // to close
if ((*selected_chn)->status == CSI_CAMERA_CHANNEL_RUNNING) {
dialog_textbox_simple("Infomation",
"The channel is Running, \nplease stop first", 6, 40);
goto again;
}
} else if (action == 1) { // to open
if ((*selected_chn)->status == CSI_CAMERA_CHANNEL_OPENED ||
(*selected_chn)->status == CSI_CAMERA_CHANNEL_RUNNING) {
dialog_textbox_simple("Infomation",
"The channel is Opened or Running, \nplease close first", 6, 40);
goto again;
}
}
/* Show message bar */
snprintf(str_buf, sizeof(str_buf),
"The Camera[%d] channel[%d] is selected\n",
cam_session->camera_id,
(*selected_chn)->chn_id);
message(str_buf, 0);
ret = 0;
break;
case 1: // need help
LOG_W("Help is not supported yet\n");
goto again;
case KEY_ESC: // specific KEY
ret = KEY_ESC;
break;
case -ERRDISPLAYTOOSMALL: // error
default:
LOG_W("Oops? why return ret=%d\n", ret);
ret = KEY_ESC;
break;
}
LOG_D("ret=%d\n", ret);
return ret;
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_enum"
#include <syslog.h>
#include <camera_manager.h>
#include <camera_app_spec.h>
#include <csi_camera_platform_spec.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
static int add_event_actions(camera_event_action_union_t *event_action)
{
int count = 0;
const camera_app_bitmasks_t *bitmasks =
camera_app_get_bitmask_array(CAMERA_APP_BITMAKS_CAMERA_EVENT_ACTION);
LOG_D("bitmasks->count=%d\n", bitmasks->count);
if (bitmasks == NULL) {
LOG_E("Can't get camera's action support list\n");
return count;
}
LOG_D("camera.action=0x%08x\n", event_action->camera.action);
switch (event_action->camera.event) {
case CSI_CAMERA_EVENT_WARNING:
case CSI_CAMERA_EVENT_ERROR:
case CSI_CAMERA_EVENT_SENSOR_FIRST_IMAGE_ARRIVE:
case CSI_CAMERA_EVENT_ISP_3A_ADJUST_READY:
for (int i = 0; i < bitmasks->count; i++) {
csi_camera_event_id_e loop_action = bitmasks->bitmask[i];
bool action_set = (event_action->camera.action & loop_action) != 0;
const char *item_name = camera_string_camera_action(loop_action);
item_make("\t%-16s(0x%08x)", item_name, loop_action);
LOG_D("\t%-16s(0x%08x)\n", item_name, loop_action);
item_set_tag(action_set ? '*' : ' ');
item_set_int(loop_action);
}
break;
}
}
int dialog_event_subscribe_action_camera(camera_event_action_union_t *event_action)
{
int ret_key = KEY_ESC;
if (event_action == NULL) {
LOG_W("event_action is NULL\n");
return KEY_ESC;
}
char *title = "Set Camera Event Action(s)";
char *prompt = "Select the Camera event then config the action(s)";
int item_pos = 0;
int list_count = 0;
again:
item_reset();
item_make("%-32s","Subscribe");
if (event_action->camera.subscribed == false) {
item_set_tag(' ');
} else {
item_set_tag('*');
list_count = add_event_actions(event_action);
}
int list_height = MIN(list_count + 8, 24);
ret_key = dialog_checkbox(
title, prompt,
CHECKLIST_HEIGTH_MIN + list_height + 2,
WIN_COLS - CHECKLIST_WIDTH_MIN - 32,
list_height, item_pos);
LOG_D("dialog_checkbox() ret_key=%d\n", ret_key);
if (ret_key == KEY_ESC) {
return KEY_ESC;
} else if (ret_key == 0) {/* select */
item_pos = item_n();
LOG_D("item_pos=%d\n", item_pos);
if (item_pos == 0) { // 1st item, which indicate whether register actions
if (item_tag() == ' ') {
event_action->camera.subscribed = true;
goto again;
} else {
event_action->camera.subscribed = false;
goto again;
}
} else { // other item, which indicate whether register actions
camera_action_e cur_action = item_int();
if (item_tag() == ' ') {
event_action->camera.action |= cur_action;
item_set_tag('*');
} else {
event_action->camera.action &= ~cur_action;
item_set_tag(' ');
}
LOG_D("camera.action=0x%08x\n", event_action->camera.action);
}
goto again;
return ret_key;
} else if (ret_key == 1) {/* Return */
return ret_key;
} else if (ret_key == 2) {/* Help */
LOG_W("Help does not support yet\n");
return ret_key;
} else {
LOG_E("Unknown return value: %d\n", ret_key);
return KEY_ESC;
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_enum"
#include <syslog.h>
#include <camera_manager.h>
#include <camera_app_spec.h>
#include <csi_camera_platform_spec.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
static int add_event_actions(camera_event_action_union_t *event_action)
{
int count = 0;
const camera_app_bitmasks_t *bitmasks =
camera_app_get_bitmask_array(CAMERA_APP_BITMAKS_CHANNEL_EVENT_ACTION);
if (bitmasks == NULL) {
LOG_E("Can't get channel's action support list\n");
return count;
}
LOG_D("camera.action=0x%08x\n", event_action->channel.action);
switch (event_action->channel.event) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY:
case CSI_CAMERA_CHANNEL_EVENT_FRAME_PUT:
case CSI_CAMERA_CHANNEL_EVENT_OVERFLOW:
for (int i = 0; i < bitmasks->count; i++) {
csi_camera_event_id_e loop_action = bitmasks->bitmask[i];
bool action_set = (event_action->channel.action & loop_action) != 0;
const char *item_name = camera_string_channel_action(loop_action);
item_make("\t%-16s(0x%08x)", item_name, loop_action);
item_set_tag(action_set ? '*' : ' ');
item_set_int(loop_action);
}
break;
}
}
int dialog_event_subscribe_action_channel(camera_event_action_union_t *event_action)
{
int ret_key = KEY_ESC;
if (event_action == NULL) {
LOG_W("event_action is NULL\n");
return KEY_ESC;
}
char *title = "Set Channel Event Action(s)";
char *prompt = "Select the channel event then config the action(s)";
int item_pos = 0;
int list_count = 0;
again:
item_reset();
item_make("%-32s","Subscribe");
if (event_action->channel.subscribed == false) {
item_set_tag(' ');
} else {
item_set_tag('*');
list_count = add_event_actions(event_action);
}
int list_height = MIN(list_count + 8, 24);
ret_key = dialog_checkbox(
title, prompt,
CHECKLIST_HEIGTH_MIN + list_height + 2,
WIN_COLS - CHECKLIST_WIDTH_MIN - 32,
list_height, item_pos);
//LOG_D("dialog_checkbox() ret_key=%d\n", ret_key);
if (ret_key == KEY_ESC) {
return KEY_ESC;
} else if (ret_key == 0) {/* select */
item_pos = item_n();
LOG_D("item_pos=%d\n", item_pos);
if (item_pos == 0) { // 1st item, which indicate whether register actions
if (item_tag() == ' ') {
event_action->channel.subscribed = true;
goto again;
} else {
event_action->channel.subscribed = false;
goto again;
}
} else { // other item, which indicate whether register actions
camera_action_e cur_action = item_int();
if (item_tag() == ' ') {
event_action->channel.action |= cur_action;
item_set_tag('*');
} else {
event_action->channel.action &= ~cur_action;
item_set_tag(' ');
}
LOG_D("camera.action=0x%08x\n", event_action->channel.action);
}
goto again;
return ret_key;
} else if (ret_key == 1) {/* Return */
return ret_key;
} else if (ret_key == 2) {/* Help */
LOG_W("Help does not support yet\n");
return ret_key;
} else {
LOG_E("Unknown return value: %d\n", ret_key);
return KEY_ESC;
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "dlg_prop_list"
#include <syslog.h>
#include <curses.h>
#include <camera_manager.h>
#include <camera_manager_utils.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
#include <csi_camera_property.h>
#include <csi_camera_platform_spec.h>
extern cams_t *cam_session;
static int fill_items(void)
{
char item_name[64];
char item_value[64];
camera_event_action_union_t *event_action;
/* Fill camera event and action */
item_make("*** Camera[%d] Event/Action ***", cam_session->camera_id);
item_set_tag(' ');
item_set_data(NULL);
for (int i = 0; i < CSI_CAMERA_EVENT_MAX_COUNT; i++) {
event_action = &(cam_session->camera_event_action[i]);
if (!event_action->camera.supported)
continue;
item_make(" %-18s", camera_string_camera_event_type(event_action->camera.event));
item_add_str("(%s) --->", event_action->camera.subscribed
? "Subscribed" : "Un-subscribed");
item_set_tag('M');
item_set_data(event_action);
//cam_mng_dump_event_action_union(event_action);
}
for(int i = 0;i < CSI_CAMERA_CHANNEL_MAX_COUNT;i++){
if((cam_session->chn_cfg[i].status == CSI_CAMERA_CHANNEL_OPENED) ||
(cam_session->chn_cfg[i].status == CSI_CAMERA_CHANNEL_RUNNING)){
item_make(" *** Channel[%d] Event/Action ***",
cam_session->chn_cfg[i].chn_id);
item_set_tag(' ');
item_set_data(NULL);
for (int j = 0; j < CSI_CAMERA_CHANNEL_EVENT_MAX_COUNT; j++) {
event_action = &(cam_session->channel_event_action[i][j]);
if (!event_action->channel.supported)
continue;
item_make(" %-18s", camera_string_channel_event_type(event_action->channel.event));
item_add_str("(%s) --->", event_action->channel.subscribed
? "Subscribed" : "Un-subscribed");
item_set_tag('N'); // Type: Channel
item_set_data(event_action);
//cam_mng_dump_event_action_union(event_action);
}
}
}
return 0;
}
int dialog_event_subscribe_action_list(camera_event_action_union_t **event_action)
{
int ret_key = KEY_ESC;
int ret = 0;
char selected_tag;
camera_event_action_union_t *selected_data;
*event_action = NULL;
char str_buf[128];
again:
item_reset();
if (fill_items() != 0) {
LOG_E("fill_items() failed\n");
ret = KEY_ESC;
goto exit;
}
int s_scroll = 0;
ret_key = dialog_menu("Camera Event Subscribe & Action Setting",
"Select the Camera/Channel, press Enter to set the event subscribe and event action",
WIN_ROWS-2, WIN_COLS, NULL, -1, &s_scroll, NULL, 0);
//LOG_D("dialog_menu() ret_key=%d, s_scroll=%d\n", ret_key, s_scroll);
switch (ret_key) {
case 0: /* Select button */
selected_tag = item_tag();
selected_data = (camera_event_action_union_t *)item_data();
if (selected_data != NULL) {
*event_action = selected_data;
ret = 0;
break;
} else {
goto again;
}
break;
case 1: /* Apply button */
ret = camera_subscribe_event(cam_session);
snprintf(str_buf, sizeof(str_buf),
"Apply Camera[%d] and Channels event register %s.",
cam_session->camera_id, (ret == 0) ? "OK" : "failed");
dialog_textbox_simple("Infomation", str_buf, 6, 56);
goto again;
case 2: /* Cancel button */
case KEY_ESC: /* Escape */
default:
ret = KEY_ESC;
goto exit;
}
exit:
return ret;
}

View File

@@ -0,0 +1,302 @@
/*
* inputbox.c -- implements the input box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
#include "app_dialogs.h"
char dialog_input_result[MAX_LEN + 1];
/*
* Print the termination buttons
*/
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
{
int x = width / 2 - 11;
int y = height - 2;
print_button(dialog, gettext(" Ok "), y, x, selected == 0);
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
wmove(dialog, y, x + 1 + 14 * selected);
wrefresh(dialog);
}
/*
* Display a dialog box for inputing a string
*/
int dialog_inputbox(const char *title, const char *prompt, int height, int width,
const char *init)
{
int i, x, y, box_y, box_x, box_width;
int input_x = 0, key = 0, button = -1;
int show_x, len, pos;
char *instr = dialog_input_result;
WINDOW *dialog;
if (!init)
instr[0] = '\0';
else
strcpy(instr, init);
do_resize:
if (WIN_ROWS <= (height - INPUTBOX_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL;
if (WIN_COLS <= (width - INPUTBOX_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */
x = (WIN_COLS - width) / 2;
y = (WIN_ROWS - height) / 2;
draw_shadow(stdscr, y, x, height, width);
dialog = newwin(height, width, y, x);
keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE);
print_title(dialog, title, width);
wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3);
/* Draw the input field box */
box_width = width - 6;
getyx(dialog, y, x);
box_y = y + 2;
box_x = (width - box_width) / 2;
draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
dlg.dialog.atr, dlg.border.atr);
print_buttons(dialog, height, width, 0);
/* Set up the initial value */
wmove(dialog, box_y, box_x);
wattrset(dialog, dlg.inputbox.atr);
len = strlen(instr);
pos = len;
if (len >= box_width) {
show_x = len - box_width + 1;
input_x = box_width - 1;
for (i = 0; i < box_width - 1; i++)
waddch(dialog, instr[show_x + i]);
} else {
show_x = 0;
input_x = len;
waddstr(dialog, instr);
}
wmove(dialog, box_y, box_x + input_x);
wrefresh(dialog);
while (key != KEY_ESC) {
key = wgetch(dialog);
if (button == -1) { /* Input box selected */
switch (key) {
case TAB:
case KEY_UP:
case KEY_DOWN:
break;
case KEY_BACKSPACE:
case 127:
if (pos) {
wattrset(dialog, dlg.inputbox.atr);
if (input_x == 0) {
show_x--;
} else
input_x--;
if (pos < len) {
for (i = pos - 1; i < len; i++) {
instr[i] = instr[i+1];
}
}
pos--;
len--;
instr[len] = '\0';
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
wrefresh(dialog);
}
continue;
case KEY_LEFT:
if (pos > 0) {
if (input_x > 0) {
wmove(dialog, box_y, --input_x + box_x);
} else if (input_x == 0) {
show_x--;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, box_x);
}
pos--;
}
continue;
case KEY_RIGHT:
if (pos < len) {
if (input_x < box_width - 1) {
wmove(dialog, box_y, ++input_x + box_x);
} else if (input_x == box_width - 1) {
show_x++;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
}
pos++;
}
continue;
default:
if (key < 0x100 && isprint(key)) {
if (len < MAX_LEN) {
wattrset(dialog, dlg.inputbox.atr);
if (pos < len) {
for (i = len; i > pos; i--)
instr[i] = instr[i-1];
instr[pos] = key;
} else {
instr[len] = key;
}
pos++;
len++;
instr[len] = '\0';
if (input_x == box_width - 1) {
show_x++;
} else {
input_x++;
}
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
wrefresh(dialog);
} else
flash(); /* Alarm user about overflow */
continue;
}
}
}
switch (key) {
case 'O':
case 'o':
delwin(dialog);
return 0;
case 'H':
case 'h':
delwin(dialog);
return 1;
case KEY_UP:
case KEY_LEFT:
switch (button) {
case -1:
button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 0:
button = -1; /* Indicates input box is selected */
print_buttons(dialog, height, width, 0);
wmove(dialog, box_y, box_x + input_x);
wrefresh(dialog);
break;
case 1:
button = 0; /* Indicates "OK" button is selected */
print_buttons(dialog, height, width, 0);
break;
}
break;
case TAB:
case KEY_DOWN:
case KEY_RIGHT:
switch (button) {
case -1:
button = 0; /* Indicates "OK" button is selected */
print_buttons(dialog, height, width, 0);
break;
case 0:
button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 1:
button = -1; /* Indicates input box is selected */
print_buttons(dialog, height, width, 0);
wmove(dialog, box_y, box_x + input_x);
wrefresh(dialog);
break;
}
break;
case ' ':
case '\n':
delwin(dialog);
return (button == -1 ? 0 : button);
case 'X':
case 'x':
key = KEY_ESC;
break;
case KEY_ESC:
key = on_key_esc(dialog);
break;
case KEY_RESIZE:
delwin(dialog);
on_key_resize();
goto do_resize;
}
}
delwin(dialog);
return KEY_ESC; /* ESC pressed */
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <curses.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "camera_demo3"
#include <syslog.h>
#include <camera_manager.h>
#include <camera_manager_utils.h>
#include <camera_string.h>
#include "param.h"
#include "app_dialogs.h"
#include "menu_process.h"
void menu_camera_process(menu_camera_item_e item)
{
int ret;
switch (item) {
case MENU_CAMERA_LIST:
LOG_D("dialog_camera_list()\n");
ret = dialog_camera_list();
break;
case MENU_CAMERA_OPEN:
LOG_D("dialog_camera_open()\n");
ret = dialog_camera_open();
break;
case MENU_CAMERA_SET_MODE:
LOG_D("dialog_camera_set_mode()\n");
ret = dialog_camera_set_mode();
break;
case MENU_CAMERA_SET_PROPERTY:
LOG_D("dialog_camera_property_list()\n");
ret = dialog_camera_property_list();
break;
case MENU_CAMERA_CLOSE:
LOG_D("dialog_camera_close()\n");
ret = dialog_camera_close();
break;
case -1:
ret = -1;
break;
default:
LOG_E("Unknown menu item:%d\n", item);
ret = -1;
}
return;
}
void menu_channel_process(menu_camera_item_e item)
{
int ret;
csi_camera_channel_cfg_s *selected_chn;
char str_buf[128];
switch (item) {
case MENU_CHANNEL_LIST:
LOG_D("channel_list()\n");
dialog_channel_list();
break;
case MENU_CHANNEL_OPEN:
again_channel_open:
LOG_D("channel_open()\n");
ret = dialog_channel_select(&selected_chn, 1);
if (ret == KEY_ESC || ret != 0 || /* Not "Select" button */
selected_chn == NULL) { /* No Channel be selected */
return;
}
ret = dialog_channel_open(selected_chn);
touchwin(stdscr);
refresh();
goto again_channel_open;
break;
case MENU_CHANNEL_CLOSE:
again_channel_close:
LOG_D("channel_close()\n");
ret = dialog_channel_select(&selected_chn, 0);
if (ret == KEY_ESC || ret != 0 || /* Not "Select" button */
selected_chn == NULL) { /* No Channel be selected */
return;
}
ret = camera_channel_close(cam_session, selected_chn->chn_id);
snprintf(str_buf, sizeof(str_buf),
"Close Camera[%d]:Channel[%d] %s",
cam_session->camera_id, selected_chn->chn_id,
(ret == 0) ? "OK" : "failed");
dialog_textbox_simple("Infomation", str_buf, 10, 40);
touchwin(stdscr);
refresh();
goto again_channel_close;
break;
case -1:
break;
default:
LOG_E("Unknown menu item:%d\n", item);
break;
}
return;
}
void menu_event_run_process(menu_camera_item_e item)
{
int ret;
char str_buf[128];
camera_event_action_union_t *event_action = NULL;
csi_camera_channel_cfg_s *selected_chn;
switch (item) {
case MENU_EVENT_SUBSCRIBE_ACTION:
again_subscribe_action:
LOG_D("dialog_event_subscribe_action_list()\n");
ret = dialog_event_subscribe_action_list(&event_action);
if (ret == KEY_ESC || ret != 0 || event_action == NULL)
return;
cam_mng_dump_event_action_union(event_action);
if (event_action->target == MANAGE_TARGET_CAMERA) {
ret = dialog_event_subscribe_action_camera(event_action);
LOG_D("dialog_event_subscribe_action_camera() ret=%d\n", ret);
goto again_subscribe_action;
} else if (event_action->target == MANAGE_TARGET_CHANNEL) {
ret = dialog_event_subscribe_action_channel(event_action);
LOG_D("dialog_event_subscribe_action_channel() ret=%d\n", ret);
goto again_subscribe_action;
}
break;
case MENU_EVENT_START_STOP:
ret = dialog_channel_run();
break;
case -1:
break;
default:
LOG_E("Unknown menu item:%d\n", item);
break;
}
return;
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <curses.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "camera_demo3"
#include <syslog.h>
#include "camera_manager.h"
#include "param.h"
#include "app_dialogs.h"
extern cams_t *cam_session;
void menu_camera_process(menu_camera_item_e item);
void menu_channel_process(menu_camera_item_e item);
void menu_event_run_process(menu_camera_item_e item);

View File

@@ -0,0 +1,442 @@
/*
* menubox.c -- implements the menu box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Changes by Clifford Wolf (god@clifford.at)
*
* [ 1998-06-13 ]
*
* *) A bugfix for the Page-Down problem
*
* *) Formerly when I used Page Down and Page Up, the cursor would be set
* to the first position in the menu box. Now lxdialog is a bit
* smarter and works more like other menu systems (just have a look at
* it).
*
* *) Formerly if I selected something my scrolling would be broken because
* lxdialog is re-invoked by the Menuconfig shell script, can't
* remember the last scrolling position, and just sets it so that the
* cursor is at the bottom of the box. Now it writes the temporary file
* lxdialog.scrltmp which contains this information. The file is
* deleted by lxdialog if the user leaves a submenu or enters a new
* one, but it would be nice if Menuconfig could make another "rm -f"
* just to be sure. Just try it out - you will recognise a difference!
*
* [ 1998-06-14 ]
*
* *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
* and menus change their size on the fly.
*
* *) If for some reason the last scrolling position is not saved by
* lxdialog, it sets the scrolling so that the selected item is in the
* middle of the menu box, not at the bottom.
*
* 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
* Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
* This fixes a bug in Menuconfig where using ' ' to descend into menus
* would leave mis-synchronized lxdialog.scrltmp files lying around,
* fscanf would read in 'scroll', and eventually that value would get used.
*/
#include "dialog.h"
#include "app_dialogs.h"
static int menu_width, item_x;
/*
* Print menu item
*/
static void do_print_item(WINDOW * win, const char *item, int line_y,
int selected, int hotkey)
{
int j;
char *menu_item = malloc(menu_width + 1);
strncpy(menu_item, item, menu_width - item_x);
menu_item[menu_width - item_x] = '\0';
j = first_alpha(menu_item, "YyNnMmHh");
/* Clear 'residue' of last item */
wattrset(win, dlg.menubox.atr);
wmove(win, line_y, 0);
#if OLD_NCURSES
{
int i;
for (i = 0; i < menu_width; i++)
waddch(win, ' ');
}
#else
wclrtoeol(win);
#endif
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
mvwaddstr(win, line_y, item_x, menu_item);
if (hotkey) {
wattrset(win, selected ? dlg.tag_key_selected.atr
: dlg.tag_key.atr);
mvwaddch(win, line_y, item_x + j, menu_item[j]);
}
if (selected) {
wmove(win, line_y, item_x + 1);
}
free(menu_item);
wrefresh(win);
}
#define print_item(index, choice, selected) \
do { \
item_set(index); \
do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
} while (0)
/*
* Print the scroll indicators.
*/
static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
int height)
{
int cur_y, cur_x;
getyx(win, cur_y, cur_x);
wmove(win, y, x);
if (scroll > 0) {
wattrset(win, dlg.uarrow.atr);
waddch(win, ACS_UARROW);
waddstr(win, "(-)");
} else {
wattrset(win, dlg.menubox.atr);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
}
y = y + height + 1;
wmove(win, y, x);
wrefresh(win);
if ((height < item_no) && (scroll + height < item_no)) {
wattrset(win, dlg.darrow.atr);
waddch(win, ACS_DARROW);
waddstr(win, "(+)");
} else {
wattrset(win, dlg.menubox_border.atr);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
waddch(win, ACS_HLINE);
}
wmove(win, cur_y, cur_x);
wrefresh(win);
}
/*
* Display the termination buttons.
*/
static void print_buttons(WINDOW * win, int height, int width, int selected,
char *button_names[], int button_count)
{
int x = width / 2 - 28;
int y = height - 2;
if (button_names == NULL) {
print_button(win, gettext("Select"), y, x + 12, selected == 0);
print_button(win, gettext("Apply"), y, x + 24, selected == 1);
print_button(win, gettext("Cancel"), y, x + 36, selected == 2);
} else {
for (int i = 0; i < button_count; i++) {
print_button(win, gettext(button_names[i]), y, x + 12 * (i + 1), selected == i);
}
}
wmove(win, y, x + 1 + 12 + 12 * selected);
wrefresh(win);
}
/* scroll up n lines (n may be negative) */
static void do_scroll(WINDOW *win, int *scroll, int n)
{
/* Scroll menu up */
scrollok(win, TRUE);
wscrl(win, n);
scrollok(win, FALSE);
*scroll = *scroll + n;
wrefresh(win);
}
/*
* Display a menu for choosing among a number of options
Indicate selected item: set 'selected' or 'selected_pos'
Indicate buttons: char *button_name[], int button_count
*/
int dialog_menu(const char *title, const char *prompt,
int height, int width,
const void *selected, int selected_pos, int *s_scroll,
char *button_names[], int button_count)
{
int i, j, x, y, box_x, box_y;
int menu_height;
int key = 0, button = 0, scroll = 0, choice = 0;
int first_item = 0, max_choice;
WINDOW *dialog, *menu;
do_resize:
//height = getmaxy(stdscr);
//width = getmaxx(stdscr);
if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN)
return -ERRDISPLAYTOOSMALL;
height -= 4;
width -= 5;
menu_height = height - 8;
max_choice = MIN(menu_height, item_count());
/* center dialog box on screen */
x = (WIN_COLS - width) / 2;
y = (WIN_ROWS - height) / 2;
draw_shadow(stdscr, y, x, height, width);
dialog = newwin(height, width, y, x);
keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dlg.dialog.atr);
wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
waddch(dialog, ACS_RTEE);
print_title(dialog, title, width);
wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3);
menu_width = width - 6;
box_y = height - menu_height - 5;
box_x = (width - menu_width) / 2 - 1;
/* create new window for the menu */
menu = subwin(dialog, menu_height, menu_width,
y + box_y + 1, x + box_x + 1);
keypad(menu, TRUE);
/* draw a box around the menu items */
draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
dlg.menubox_border.atr, dlg.menubox.atr);
if (menu_width >= 60)
item_x = (menu_width - 50) / 3;
else
item_x = 4;
/* Set choice to default item */
item_foreach() {
if (selected && (selected == item_data()))
choice = item_n();
}
if (selected_pos >= 0)
choice = selected_pos;
/* get the saved scroll info */
scroll = *s_scroll;
if ((scroll <= choice) && (scroll + max_choice > choice) &&
(scroll >= 0) && (scroll + max_choice <= item_count())) {
first_item = scroll;
choice = choice - scroll;
} else {
scroll = 0;
}
if ((choice >= max_choice)) {
if (choice >= item_count() - max_choice / 2)
scroll = first_item = item_count() - max_choice;
else
scroll = first_item = choice - max_choice / 2;
choice = choice - scroll;
}
/* Print the menu */
for (i = 0; i < max_choice; i++) {
print_item(first_item + i, i, i == choice);
}
wnoutrefresh(menu);
print_arrows(dialog, item_count(), scroll,
box_y, box_x + item_x + 1, menu_height);
print_buttons(dialog, height, width, 0, button_names, button_count);
wmove(menu, choice, item_x + 1);
wrefresh(menu);
while (key != KEY_ESC) {
key = wgetch(menu);
if (key < 256 && isalpha(key))
key = tolower(key);
if (strchr("ynmh ", key))
i = max_choice;
else {
for (i = choice + 1; i < max_choice; i++) {
item_set(scroll + i);
j = first_alpha(item_str(), "YyNnMmHh");
if (key == tolower(item_str()[j]))
break;
}
if (i == max_choice)
for (i = 0; i < max_choice; i++) {
item_set(scroll + i);
j = first_alpha(item_str(), "YyNnMmHh");
if (key == tolower(item_str()[j]))
break;
}
}
if (item_count() != 0 &&
(i < max_choice ||
key == KEY_UP || key == KEY_DOWN ||
key == '-' || key == '+' ||
key == KEY_PPAGE || key == KEY_NPAGE)) {
/* Remove highligt of current item */
print_item(scroll + choice, choice, FALSE);
if (key == KEY_UP || key == '-') {
if (choice < 2 && scroll) {
/* Scroll menu down */
do_scroll(menu, &scroll, -1);
print_item(scroll, 0, FALSE);
} else
choice = MAX(choice - 1, 0);
} else if (key == KEY_DOWN || key == '+') {
print_item(scroll+choice, choice, FALSE);
if ((choice > max_choice - 3) &&
(scroll + max_choice < item_count())) {
/* Scroll menu up */
do_scroll(menu, &scroll, 1);
print_item(scroll+max_choice - 1,
max_choice - 1, FALSE);
} else
choice = MIN(choice + 1, max_choice - 1);
} else if (key == KEY_PPAGE) {
scrollok(menu, TRUE);
for (i = 0; (i < max_choice); i++) {
if (scroll > 0) {
do_scroll(menu, &scroll, -1);
print_item(scroll, 0, FALSE);
} else {
if (choice > 0)
choice--;
}
}
} else if (key == KEY_NPAGE) {
for (i = 0; (i < max_choice); i++) {
if (scroll + max_choice < item_count()) {
do_scroll(menu, &scroll, 1);
print_item(scroll+max_choice-1,
max_choice - 1, FALSE);
} else {
if (choice + 1 < max_choice)
choice++;
}
}
} else
choice = i;
print_item(scroll + choice, choice, TRUE);
print_arrows(dialog, item_count(), scroll,
box_y, box_x + item_x + 1, menu_height);
wnoutrefresh(dialog);
wrefresh(menu);
continue; /* wait for another key press */
}
switch (key) {
case KEY_LEFT:
case TAB:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0) ?
2 : (button > 2 ? 0 : button);
print_buttons(dialog, height, width, button, button_names, button_count);
wrefresh(menu);
break;
case ' ':
case 'S':
case 's':
case 'A':
case 'a':
case 'C':
case 'c':
case '\n':
/* save scroll info */
*s_scroll = scroll;
delwin(menu);
delwin(dialog);
item_set(scroll + choice);
item_set_selected(1);
switch (key) {
case 'S':
case 's':
return 0;
case 'A':
case 'a':
return 1;
case 'C':
case 'c':
return 2;
case '\n':
return button;
}
return 0;
case 'e':
case 'x':
key = KEY_ESC;
break;
case KEY_ESC:
key = on_key_esc(menu);
break;
case KEY_RESIZE:
on_key_resize();
delwin(menu);
delwin(dialog);
goto do_resize;
}
}
delwin(menu);
delwin(dialog);
return key; /* ESC pressed */
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <string.h>
#include <stdlib.h>
#include "param.h"
char param[10][10][MENU_ITEM_MAX_LEN+1];
static void GetSubStr(char *des, char *src, char ch, int n)
{
int i, len;
char *p1, *p, tmp[300];
strcpy(tmp, src);
*des = 0;
p1 = tmp;
for (int i = 0; i < n; i++) {
p = (char *)strchr(p1, ch);
if (p != NULL) {
*p++ = 0;
p1 = p;
}
}
p = (char *)strchr(p1, ch);
if (p != NULL) {
*p = 0;
strcpy(des, p1);
}
}
int get_param(char *name)
{
FILE *fp;
char ss[201], xm[3], gs[3];
int i, j;
sprintf(ss, "%s.conf", name);
if ((fp = fopen(ss, "r")) == NULL) return (-1);
for (j = 0; j < 10; j++)
for (i = 0; i < 10; i++)
memset(param[j][i], 0, 13);
while (1) {
memset(ss, 0, 201);
fgets(ss, 200, fp);
if (feof(fp)) break;
if (ss[0] == '#') continue;
GetSubStr(xm, ss, '|', 0);
GetSubStr(gs, ss, '|', 1);
j = atoi(xm);
for (i = 1; i <= atoi(gs); i++) {
sprintf(param[j][0], "%s", gs);
GetSubStr(param[j][i], ss, '|', i + 1);
}
}
fclose(fp);
return (0);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __PARAM_H__
#define __PARAM_H__
#include <curses.h>
#define MENU_ITEM_MAX_LEN 16
extern char param[10][10][MENU_ITEM_MAX_LEN+1];
int get_param(char *name);
#define MENU_CAMERA 1
typedef enum {
MENU_CAMERA_LIST = 0,
MENU_CAMERA_OPEN,
MENU_CAMERA_SET_MODE,
MENU_CAMERA_SET_PROPERTY,
MENU_CAMERA_CLOSE,
} menu_camera_item_e;
#define MENU_CHANNEL 2
typedef enum {
MENU_CHANNEL_LIST = 0,
MENU_CHANNEL_OPEN,
MENU_CHANNEL_CLOSE,
} menu_channel_item_e;
#define MENU_EVENT_RUN 3
typedef enum {
MENU_EVENT_SUBSCRIBE_ACTION = 0,
MENU_EVENT_START_STOP,
} menu_event_run_item_e;
#endif /* __PARAM_H__ */

View File

@@ -0,0 +1,414 @@
/*
* textbox.c -- implements the text box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
#include "app_dialogs.h"
static void back_lines(int n);
static void print_page(WINDOW *win, int height, int width, update_text_fn
update_text, void *data);
static void print_line(WINDOW *win, int row, int width);
static char *get_line(void);
static void print_position(WINDOW * win);
static int hscroll;
static int begin_reached, end_reached, page_length;
static char *buf;
static char *page;
/*
* refresh window content
*/
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
int cur_y, int cur_x, update_text_fn update_text,
void *data)
{
print_page(box, boxh, boxw, update_text, data);
print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
}
/*
* Display text from a file in a dialog box.
*
* keys is a null-terminated array
* update_text() may not add or remove any '\n' or '\0' in tbuf
*/
int dialog_textbox(const char *title, char *tbuf, int initial_height,
int initial_width, int *keys, int *_vscroll, int *_hscroll,
update_text_fn update_text, void *data)
{
int i, x, y, cur_x, cur_y, key = 0;
int height, width, boxh, boxw;
WINDOW *dialog, *box;
bool done = false;
begin_reached = 1;
end_reached = 0;
page_length = 0;
hscroll = 0;
buf = tbuf;
page = buf; /* page is pointer to start of page to be displayed */
if (_vscroll && *_vscroll) {
begin_reached = 0;
for (i = 0; i < *_vscroll; i++)
get_line();
}
if (_hscroll)
hscroll = *_hscroll;
do_resize:
getmaxyx(stdscr, height, width);
if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN)
return -ERRDISPLAYTOOSMALL;
if (initial_height != 0)
height = initial_height;
else
if (height > 4)
height -= 4;
else
height = 0;
if (initial_width != 0)
width = initial_width;
else
if (width > 5)
width -= 5;
else
width = 0;
/* center dialog box on screen */
x = (WIN_COLS - width) / 2;
y = (WIN_ROWS - height) / 2;
draw_shadow(stdscr, y, x, height, width);
dialog = newwin(height, width, y, x);
keypad(dialog, TRUE);
/* Create window for box region, used for scrolling text */
boxh = height - 4;
boxw = width - 2;
box = subwin(dialog, boxh, boxw, y + 1, x + 1);
wattrset(box, dlg.dialog.atr);
wbkgdset(box, dlg.dialog.atr & A_COLOR);
keypad(box, TRUE);
/* register the new window, along with its borders */
draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dlg.dialog.atr);
wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
waddch(dialog, ACS_RTEE);
print_title(dialog, title, width);
print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
wnoutrefresh(dialog);
getyx(dialog, cur_y, cur_x); /* Save cursor position */
/* Print first page of text */
attr_clear(box, boxh, boxw, dlg.dialog.atr);
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
data);
while (!done) {
key = wgetch(dialog);
switch (key) {
case 'E': /* Exit */
case 'e':
case 'X':
case 'x':
case 'q':
case '\n':
done = true;
break;
case 'g': /* First page */
case KEY_HOME:
if (!begin_reached) {
begin_reached = 1;
page = buf;
refresh_text_box(dialog, box, boxh, boxw,
cur_y, cur_x, update_text,
data);
}
break;
case 'G': /* Last page */
case KEY_END:
end_reached = 1;
/* point to last char in buf */
page = buf + strlen(buf);
back_lines(boxh);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case 'K': /* Previous line */
case 'k':
case KEY_UP:
if (begin_reached)
break;
back_lines(page_length + 1);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case 'B': /* Previous page */
case 'b':
case 'u':
case KEY_PPAGE:
if (begin_reached)
break;
back_lines(page_length + boxh);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case 'J': /* Next line */
case 'j':
case KEY_DOWN:
if (end_reached)
break;
back_lines(page_length - 1);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case KEY_NPAGE: /* Next page */
case ' ':
case 'd':
if (end_reached)
break;
begin_reached = 0;
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case '0': /* Beginning of line */
case 'H': /* Scroll left */
case 'h':
case KEY_LEFT:
if (hscroll <= 0)
break;
if (key == '0')
hscroll = 0;
else
hscroll--;
/* Reprint current page to scroll horizontally */
back_lines(page_length);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case 'L': /* Scroll right */
case 'l':
case KEY_RIGHT:
if (hscroll >= MAX_LEN)
break;
hscroll++;
/* Reprint current page to scroll horizontally */
back_lines(page_length);
refresh_text_box(dialog, box, boxh, boxw, cur_y,
cur_x, update_text, data);
break;
case KEY_ESC:
if (on_key_esc(dialog) == KEY_ESC)
done = true;
break;
case KEY_RESIZE:
back_lines(height);
delwin(box);
delwin(dialog);
on_key_resize();
goto do_resize;
default:
for (i = 0; keys[i]; i++) {
if (key == keys[i]) {
done = true;
break;
}
}
}
}
delwin(box);
delwin(dialog);
if (_vscroll) {
const char *s;
s = buf;
*_vscroll = 0;
back_lines(page_length);
while (s < page && (s = strchr(s, '\n'))) {
(*_vscroll)++;
s++;
}
}
if (_hscroll)
*_hscroll = hscroll;
return key;
}
int dialog_textbox_simple(const char *title, char *tbuf, int initial_height, int initial_width)
{
return dialog_textbox(title, tbuf,initial_height, initial_width,
(int []) {0}, NULL, NULL, NULL, NULL);
}
/*
* Go back 'n' lines in text. Called by dialog_textbox().
* 'page' will be updated to point to the desired line in 'buf'.
*/
static void back_lines(int n)
{
int i;
begin_reached = 0;
/* Go back 'n' lines */
for (i = 0; i < n; i++) {
if (*page == '\0') {
if (end_reached) {
end_reached = 0;
continue;
}
}
if (page == buf) {
begin_reached = 1;
return;
}
page--;
do {
if (page == buf) {
begin_reached = 1;
return;
}
page--;
} while (*page != '\n');
page++;
}
}
/*
* Print a new page of text.
*/
static void print_page(WINDOW *win, int height, int width, update_text_fn
update_text, void *data)
{
int i, passed_end = 0;
if (update_text) {
char *end;
for (i = 0; i < height; i++)
get_line();
end = page;
back_lines(height);
update_text(buf, page - buf, end - buf, data);
}
page_length = 0;
for (i = 0; i < height; i++) {
print_line(win, i, width);
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
wnoutrefresh(win);
}
/*
* Print a new line of text.
*/
static void print_line(WINDOW * win, int row, int width)
{
char *line;
line = get_line();
line += MIN(strlen(line), hscroll); /* Scroll horizontally */
wmove(win, row, 0); /* move cursor to correct line */
waddch(win, ' ');
waddnstr(win, line, MIN(strlen(line), width - 2));
/* Clear 'residue' of previous line */
#if OLD_NCURSES
{
int x = getcurx(win);
int i;
for (i = 0; i < width - x; i++)
waddch(win, ' ');
}
#else
wclrtoeol(win);
#endif
}
/*
* Return current line of text. Called by dialog_textbox() and print_line().
* 'page' should point to start of current line before calling, and will be
* updated to point to start of next line.
*/
static char *get_line(void)
{
int i = 0;
static char line[MAX_LEN + 1];
end_reached = 0;
while (*page != '\n') {
if (*page == '\0') {
end_reached = 1;
break;
} else if (i < MAX_LEN)
line[i++] = *(page++);
else {
/* Truncate lines longer than MAX_LEN characters */
if (i == MAX_LEN)
line[i++] = '\0';
page++;
}
}
if (i <= MAX_LEN)
line[i] = '\0';
if (!end_reached)
page++; /* move past '\n' */
return line;
}
/*
* Print current position
*/
static void print_position(WINDOW * win)
{
int percent;
wattrset(win, dlg.position_indicator.atr);
wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
percent = (page - buf) * 100 / strlen(buf);
wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
wprintw(win, "(%3d%%)", percent);
}

View File

@@ -0,0 +1,735 @@
/*
* util.c
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdarg.h>
#include "dialog.h"
/* Needed in signal handler in mconf.c */
int saved_x, saved_y;
struct dialog_info dlg;
static void set_mono_theme(void)
{
dlg.screen.atr = A_NORMAL;
dlg.shadow.atr = A_NORMAL;
dlg.dialog.atr = A_NORMAL;
dlg.title.atr = A_BOLD;
dlg.border.atr = A_NORMAL;
dlg.button_active.atr = A_REVERSE;
dlg.button_inactive.atr = A_DIM;
dlg.button_key_active.atr = A_REVERSE;
dlg.button_key_inactive.atr = A_BOLD;
dlg.button_label_active.atr = A_REVERSE;
dlg.button_label_inactive.atr = A_NORMAL;
dlg.inputbox.atr = A_NORMAL;
dlg.inputbox_border.atr = A_NORMAL;
dlg.searchbox.atr = A_NORMAL;
dlg.searchbox_title.atr = A_BOLD;
dlg.searchbox_border.atr = A_NORMAL;
dlg.position_indicator.atr = A_BOLD;
dlg.menubox.atr = A_NORMAL;
dlg.menubox_border.atr = A_NORMAL;
dlg.item.atr = A_NORMAL;
dlg.item_selected.atr = A_REVERSE;
dlg.tag.atr = A_BOLD;
dlg.tag_selected.atr = A_REVERSE;
dlg.tag_key.atr = A_BOLD;
dlg.tag_key_selected.atr = A_REVERSE;
dlg.check.atr = A_BOLD;
dlg.check_selected.atr = A_REVERSE;
dlg.uarrow.atr = A_BOLD;
dlg.darrow.atr = A_BOLD;
}
#define DLG_COLOR(dialog, f, b, h) \
do { \
dlg.dialog.fg = (f); \
dlg.dialog.bg = (b); \
dlg.dialog.hl = (h); \
} while (0)
static void set_classic_theme(void)
{
DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true);
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false);
DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true);
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false);
DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true);
DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true);
}
static void set_blackbg_theme(void)
{
DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true);
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false);
DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true);
DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false);
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false);
DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false);
DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true);
DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
}
static void set_bluetitle_theme(void)
{
set_classic_theme();
DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
}
/*
* Select color theme
*/
static int set_theme(const char *theme)
{
int use_color = 1;
if (!theme)
set_bluetitle_theme();
else if (strcmp(theme, "classic") == 0)
set_classic_theme();
else if (strcmp(theme, "bluetitle") == 0)
set_bluetitle_theme();
else if (strcmp(theme, "blackbg") == 0)
set_blackbg_theme();
else if (strcmp(theme, "mono") == 0)
use_color = 0;
return use_color;
}
static void init_one_color(struct dialog_color *color)
{
static int pair = 10;
pair++;
init_pair(pair, color->fg, color->bg);
if (color->hl)
color->atr = A_BOLD | COLOR_PAIR(pair);
else
color->atr = COLOR_PAIR(pair);
}
static void init_dialog_colors(void)
{
init_one_color(&dlg.screen);
init_one_color(&dlg.shadow);
init_one_color(&dlg.dialog);
init_one_color(&dlg.title);
init_one_color(&dlg.border);
init_one_color(&dlg.button_active);
init_one_color(&dlg.button_inactive);
init_one_color(&dlg.button_key_active);
init_one_color(&dlg.button_key_inactive);
init_one_color(&dlg.button_label_active);
init_one_color(&dlg.button_label_inactive);
init_one_color(&dlg.inputbox);
init_one_color(&dlg.inputbox_border);
init_one_color(&dlg.searchbox);
init_one_color(&dlg.searchbox_title);
init_one_color(&dlg.searchbox_border);
init_one_color(&dlg.position_indicator);
init_one_color(&dlg.menubox);
init_one_color(&dlg.menubox_border);
init_one_color(&dlg.item);
init_one_color(&dlg.item_selected);
init_one_color(&dlg.tag);
init_one_color(&dlg.tag_selected);
init_one_color(&dlg.tag_key);
init_one_color(&dlg.tag_key_selected);
init_one_color(&dlg.check);
init_one_color(&dlg.check_selected);
init_one_color(&dlg.uarrow);
init_one_color(&dlg.darrow);
}
/*
* Setup for color display
*/
static void color_setup(const char *theme)
{
int use_color;
use_color = set_theme(theme);
if (use_color && has_colors()) {
start_color();
init_dialog_colors();
} else
set_mono_theme();
}
/*
* Set window to attribute 'attr'
*/
void attr_clear(WINDOW * win, int height, int width, chtype attr)
{
int i, j;
wattrset(win, attr);
for (i = 0; i < height; i++) {
wmove(win, i, 0);
for (j = 0; j < width; j++)
waddch(win, ' ');
}
touchwin(win);
}
void dialog_clear(void)
{
int lines, columns;
lines = getmaxy(stdscr);
columns = getmaxx(stdscr);
attr_clear(stdscr, lines, columns, dlg.screen.atr);
/* Display background title if it exists ... - SLH */
if (dlg.backtitle != NULL) {
int i, len = 0, skip = 0;
struct subtitle_list *pos;
wattrset(stdscr, dlg.screen.atr);
mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
/* 3 is for the arrow and spaces */
len += strlen(pos->text) + 3;
}
wmove(stdscr, 1, 1);
if (len > columns - 2) {
const char *ellipsis = "[...] ";
waddstr(stdscr, ellipsis);
skip = len - (columns - 2 - strlen(ellipsis));
}
for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
if (skip == 0)
waddch(stdscr, ACS_RARROW);
else
skip--;
if (skip == 0)
waddch(stdscr, ' ');
else
skip--;
if (skip < strlen(pos->text)) {
waddstr(stdscr, pos->text + skip);
skip = 0;
} else
skip -= strlen(pos->text);
if (skip == 0)
waddch(stdscr, ' ');
else
skip--;
}
for (i = len + 1; i < columns - 1; i++)
waddch(stdscr, ACS_HLINE);
}
wnoutrefresh(stdscr);
}
/*
* Do some initialization for dialog
*/
int init_dialog(const char *backtitle)
{
int height, width;
//initscr(); /* Init curses */
/* Get current cursor position for signal handler in mconf.c */
getyx(stdscr, saved_y, saved_x);
getmaxyx(stdscr, height, width);
if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) {
endwin();
return -ERRDISPLAYTOOSMALL;
}
dlg.backtitle = backtitle;
color_setup("classic");
keypad(stdscr, TRUE);
cbreak();
noecho();
dialog_clear();
return 0;
}
void set_dialog_backtitle(const char *backtitle)
{
dlg.backtitle = backtitle;
}
void set_dialog_subtitles(struct subtitle_list *subtitles)
{
dlg.subtitles = subtitles;
}
/*
* End using dialog functions.
*/
void end_dialog(int x, int y)
{
/* move cursor back to original position */
move(y, x);
refresh();
endwin();
}
/* Print the title of the dialog. Center the title and truncate
* tile if wider than dialog (- 2 chars).
**/
void print_title(WINDOW *dialog, const char *title, int width)
{
if (title) {
int tlen = MIN(width - 2, strlen(title));
wattrset(dialog, dlg.title.atr);
mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
waddch(dialog, ' ');
}
}
/*
* Print a string of text in a window, automatically wrap around to the
* next line if the string is too long to fit on one line. Newline
* characters '\n' are propperly processed. We start on a new line
* if there is no room for at least 4 nonblanks following a double-space.
*/
void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
{
int newl, cur_x, cur_y;
int prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;
strcpy(tempstr, prompt);
prompt_len = strlen(tempstr);
if (prompt_len <= width - x * 2) { /* If prompt is short */
wmove(win, y, (width - prompt_len) / 2);
waddstr(win, tempstr);
} else {
cur_x = x;
cur_y = y;
newl = 1;
word = tempstr;
while (word && *word) {
sp = strpbrk(word, "\n ");
if (sp && *sp == '\n')
newline_separator = sp;
if (sp)
*sp++ = 0;
/* Wrap to next line if either the word does not fit,
or it is the first word of a new sentence, and it is
short, and the next word does not fit. */
room = width - cur_x;
wlen = strlen(word);
if (wlen > room ||
(newl && wlen < 4 && sp
&& wlen + 1 + strlen(sp) > room
&& (!(sp2 = strpbrk(sp, "\n "))
|| wlen + 1 + (sp2 - sp) > room))) {
cur_y++;
cur_x = x;
}
wmove(win, cur_y, cur_x);
waddstr(win, word);
getyx(win, cur_y, cur_x);
/* Move to the next line if the word separator was a newline */
if (newline_separator) {
cur_y++;
cur_x = x;
newline_separator = 0;
} else
cur_x++;
if (sp && *sp == ' ') {
cur_x++; /* double space */
while (*++sp == ' ') ;
newl = 1;
} else
newl = 0;
word = sp;
}
}
}
/*
* Print a button
*/
void print_button(WINDOW * win, const char *label, int y, int x, int selected)
{
int i, temp;
wmove(win, y, x);
wattrset(win, selected ? dlg.button_active.atr
: dlg.button_inactive.atr);
waddstr(win, "<");
temp = strspn(label, " ");
label += temp;
wattrset(win, selected ? dlg.button_label_active.atr
: dlg.button_label_inactive.atr);
for (i = 0; i < temp; i++)
waddch(win, ' ');
wattrset(win, selected ? dlg.button_key_active.atr
: dlg.button_key_inactive.atr);
waddch(win, label[0]);
wattrset(win, selected ? dlg.button_label_active.atr
: dlg.button_label_inactive.atr);
waddstr(win, (char *)label + 1);
wattrset(win, selected ? dlg.button_active.atr
: dlg.button_inactive.atr);
waddstr(win, ">");
wmove(win, y, x + temp + 1);
}
/*
* Draw a rectangular box with line drawing characters
*/
void
draw_box(WINDOW * win, int y, int x, int height, int width,
chtype box, chtype border)
{
int i, j;
wattrset(win, 0);
for (i = 0; i < height; i++) {
wmove(win, y + i, x);
for (j = 0; j < width; j++)
if (!i && !j)
waddch(win, border | ACS_ULCORNER);
else if (i == height - 1 && !j)
waddch(win, border | ACS_LLCORNER);
else if (!i && j == width - 1)
waddch(win, box | ACS_URCORNER);
else if (i == height - 1 && j == width - 1)
waddch(win, box | ACS_LRCORNER);
else if (!i)
waddch(win, border | ACS_HLINE);
else if (i == height - 1)
waddch(win, box | ACS_HLINE);
else if (!j)
waddch(win, border | ACS_VLINE);
else if (j == width - 1)
waddch(win, box | ACS_VLINE);
else
waddch(win, box | ' ');
}
}
/*
* Draw shadows along the right and bottom edge to give a more 3D look
* to the boxes
*/
void draw_shadow(WINDOW * win, int y, int x, int height, int width)
{
int i;
if (has_colors()) { /* Whether terminal supports color? */
wattrset(win, dlg.shadow.atr);
wmove(win, y + height, x + 2);
for (i = 0; i < width; i++)
waddch(win, winch(win) & A_CHARTEXT);
for (i = y + 1; i < y + height + 1; i++) {
wmove(win, i, x + width);
waddch(win, winch(win) & A_CHARTEXT);
waddch(win, winch(win) & A_CHARTEXT);
}
wnoutrefresh(win);
}
}
/*
* Return the position of the first alphabetic character in a string.
*/
int first_alpha(const char *string, const char *exempt)
{
int i, in_paren = 0, c;
for (i = 0; i < strlen(string); i++) {
c = tolower(string[i]);
if (strchr("<[(", c))
++in_paren;
if (strchr(">])", c) && in_paren > 0)
--in_paren;
if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
return i;
}
return 0;
}
/*
* ncurses uses ESC to detect escaped char sequences. This resutl in
* a small timeout before ESC is actually delivered to the application.
* lxdialog suggest <ESC> <ESC> which is correctly translated to two
* times esc. But then we need to ignore the second esc to avoid stepping
* out one menu too much. Filter away all escaped key sequences since
* keypad(FALSE) turn off ncurses support for escape sequences - and thats
* needed to make notimeout() do as expected.
*/
int on_key_esc(WINDOW *win)
{
int key;
int key2;
int key3;
nodelay(win, TRUE);
keypad(win, FALSE);
key = wgetch(win);
key2 = wgetch(win);
do {
key3 = wgetch(win);
} while (key3 != ERR);
nodelay(win, FALSE);
keypad(win, TRUE);
if (key == KEY_ESC && key2 == ERR)
return KEY_ESC;
else if (key != ERR && key != KEY_ESC && key2 == ERR)
ungetch(key);
return -1;
}
/* redraw screen in new size */
int on_key_resize(void)
{
dialog_clear();
return KEY_RESIZE;
}
struct dialog_list *item_cur;
struct dialog_list item_nil;
struct dialog_list *item_head;
void item_reset(void)
{
struct dialog_list *p, *next;
for (p = item_head; p; p = next) {
next = p->next;
free(p);
}
item_head = NULL;
item_cur = &item_nil;
}
void item_make(const char *fmt, ...)
{
va_list ap;
struct dialog_list *p = malloc(sizeof(*p));
if (item_head)
item_cur->next = p;
else
item_head = p;
item_cur = p;
memset(p, 0, sizeof(*p));
va_start(ap, fmt);
vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
va_end(ap);
}
void item_add_str(const char *fmt, ...)
{
va_list ap;
size_t avail;
avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
va_start(ap, fmt);
vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
avail, fmt, ap);
item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
va_end(ap);
}
void item_set_tag(char tag)
{
item_cur->node.tag = tag;
}
void item_set_int(int int_value)
{
item_cur->node.int_value = int_value;
}
void item_set_data(void *ptr)
{
item_cur->node.data = ptr;
}
void item_set_selected(int val)
{
item_cur->node.selected = val;
}
int item_activate_selected(void)
{
item_foreach()
if (item_is_selected())
return 1;
return 0;
}
int item_activate_selected_pos(void)
{
int i = 0;
item_foreach() {
if (item_is_selected())
return i;
i++;
}
return -1;
}
void *item_data(void)
{
return item_cur->node.data;
}
char item_tag(void)
{
return item_cur->node.tag;
}
int item_int(void)
{
return item_cur->node.int_value;
}
int item_count(void)
{
int n = 0;
struct dialog_list *p;
for (p = item_head; p; p = p->next)
n++;
return n;
}
void item_set(int n)
{
int i = 0;
item_foreach()
if (i++ == n)
return;
}
int item_n(void)
{
int n = 0;
struct dialog_list *p;
for (p = item_head; p; p = p->next) {
if (p == item_cur)
return n;
n++;
}
return 0;
}
const char *item_str(void)
{
return item_cur->node.str;
}
int item_is_selected(void)
{
return (item_cur->node.selected != 0);
}
int item_is_tag(char tag)
{
return (item_cur->node.tag == tag);
}

View File

@@ -0,0 +1,123 @@
/*
* yesno.c -- implements the yes/no box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define LOG_LEVEL 2
//#define LOG_PREFIX ""
#include <syslog.h>
#include "dialog.h"
#include "app_dialogs.h"
/*
* Display termination buttons
*/
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
{
int x = width / 2 - 10;
int y = height - 2;
print_button(dialog, gettext(" Yes "), y, x, selected == 0);
print_button(dialog, gettext(" No "), y, x + 13, selected == 1);
wmove(dialog, y, x + 1 + 13 * selected);
wrefresh(dialog);
}
/*
* Display a dialog box with two buttons - Yes and No
*/
int dialog_yesno(const char *title, const char *prompt, int height, int width)
{
int i, x, y, key = 0, button = 0;
WINDOW *dialog;
do_resize:
if (WIN_ROWS < (height + YESNO_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL;
if (WIN_COLS < (width + YESNO_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL;
/* center dialog box on screen */
x = (WIN_COLS - width) / 2;
y = (WIN_ROWS - height) / 2;
draw_shadow(stdscr, y, x, height, width);
dialog = newwin(height, width, y, x);
keypad(dialog, TRUE);
//wbkgd(dialog, COLOR_PAIR(0));
draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr);
mvwaddch(dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dlg.dialog.atr);
waddch(dialog, ACS_RTEE);
print_title(dialog, title, width);
wattrset(dialog, dlg.dialog.atr);
print_autowrap(dialog, prompt, width - 2, 1, 3);
print_buttons(dialog, height, width, 0);
while (key != KEY_ESC) {
key = wgetch(dialog);
switch (key) {
case 'Y':
case 'y':
delwin(dialog);
return 0;
case 'N':
case 'n':
delwin(dialog);
return 1;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh(dialog);
break;
case ' ':
case '\n':
delwin(dialog);
return button;
case KEY_ESC:
key = on_key_esc(dialog);
break;
case KEY_RESIZE:
//delwin(dialog);
//on_key_resize();
//goto do_resize;
;
}
}
delwin(dialog);
return key; /* ESC pressed */
}

View File

@@ -0,0 +1,297 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "camera_demo4"
#include <syslog.h>
#include <csi_frame.h>
#include <csi_camera.h>
#define TEST_DEVICE_NAME "/dev/video0"
typedef struct cam_channel_control {
pthread_t thread_id;
bool run;
csi_cam_handle_t cam_handle;
csi_camera_channel_cfg_s chn_cfg;
} cam_channel_control_t;
static void dump_camera_meta(csi_frame_s *frame);
static void *channel_thread(void *arg);
int main(int argc, char *argv[])
{
bool running = true;
csi_camera_info_s camera_info;
// 获取设备中所有的Camera
struct csi_camera_infos camera_infos;
csi_camera_query_list(&camera_infos);
LOG_O("csi_camera_query_list() OK\n");
// 打印所有设备所支持的Camera
for (uint32_t i = 0; i < camera_infos.count; i++) {
printf("Camera[%d]: camera_name='%s', device_name='%s', bus_info='%s', capabilities=0x%08x\n",
i, camera_infos.info[i].camera_name, camera_infos.info[i].device_name,
camera_infos.info[i].bus_info, camera_infos.info[i].capabilities);
}
/* Camera[0]: camera_name='RGB_Camera', device_name='/dev/video0', bus_info='CSI-MIPI', capabilities=0x00800001
* Camera[1]: camera_name:'Mono_Camera', device_name:'/dev/video8', bus_info='USB', capabilities=0x00000001
*/
bool found_camera = false;
for (uint32_t i = 0; i < camera_infos.count; i++) {
if (strcmp(camera_infos.info[i].device_name, TEST_DEVICE_NAME) == 0) {
camera_info = camera_infos.info[i];
printf("found device_name:'%s'\n", camera_info.device_name);
found_camera = true;
break;
}
}
if (!found_camera) {
LOG_E("Can't find camera_name:'%s'\n", TEST_DEVICE_NAME);
exit(-1);
}
printf("The caps are:\n");
for (uint32_t i = 1; i < 0x80000000; i = i << 1) {
switch (camera_info.capabilities & i) {
case CSI_CAMERA_CAP_VIDEO_CAPTURE:
printf("\t Video capture\n");
break;
case CSI_CAMERA_CAP_META_CAPTURE:
printf("\t metadata capture\n");
break;
default:
if (camera_info.capabilities & i) {
printf("\t unknown capabilities(0x%08x)\n", camera_info.capabilities & i);
}
break;
}
}
/* The caps are: Video capture, metadata capture */
// 打开Camera设备获取句柄作为后续操对象
csi_cam_handle_t cam_handle;
csi_camera_open(&cam_handle, camera_info.device_name);
LOG_O("csi_camera_open() OK\n");
// 获取Camera支持的工作模式
struct csi_camera_modes camera_modes;
camera_modes.count = 0;
csi_camera_get_modes(cam_handle, &camera_modes);
LOG_O("csi_camera_get_modes() OK\n");
// 打印camera所支持的所有工作模式
printf(" Camera:'%s' modes are:{\n", TEST_DEVICE_NAME);
for (uint32_t i = 0; i < camera_modes.count; i++) {
printf("\t mode_id=%d: description:'%s'\n",
camera_modes.modes[i].mode_id, camera_modes.modes[i].description);
}
printf("}\n");
// 设置camera的工作模式及其配置
csi_camera_mode_cfg_s camera_cfg;
camera_cfg.mode_id = 1;
camera_cfg.calibriation = NULL; // 采用系统默认配置
camera_cfg.lib3a = NULL; // 采用系统默认配置
csi_camera_set_mode(cam_handle, &camera_cfg);
// 获取单个可控单元的属性
csi_camera_property_description_s description;
description.id = CSI_CAMERA_PID_HFLIP;
csi_camera_query_property(cam_handle, &description);
printf("properity id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.bool_value, description.value.bool_value);
/* id=0x0098090x, type=2 default=0 value=1 */
/* Other example:
* id=0x0098090y, type=3 min=0 max=255 step=1 default=127 value=116
* id=0x0098090z, type=4 min=0 max=3 default=0 value=2
* 0: IDLE
* 1: BUSY
* 2: REACHED
* 3: FAILED
*/
// 轮询获取所有可控制的单元
description.id = CSI_CAMERA_PID_HFLIP;
while (!csi_camera_query_property(cam_handle, &description)) {
//printf(...); // 打印属性
description.id |= CSI_CAMERA_FLAG_NEXT_CTRL;
}
LOG_O("csi_camera_query_property() OK\n");
// 同时配置多个参数
csi_camera_properties_s properties;
csi_camera_property_s property[2];
property[0].id = CSI_CAMERA_PID_HFLIP;
property[0].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
property[0].value.bool_value = true;
property[0].id = CSI_CAMERA_PID_VFLIP;
property[0].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
property[0].value.bool_value = true;
properties.count = 2;
properties.property = property;
csi_camera_get_property(cam_handle, &properties);
LOG_O("csi_camera_get_property() OK\n");
cam_channel_control_t channel_control[2];
for (int i = 0; i < 2; i++) {
cam_channel_control_t *chn_ctrl = &channel_control[i];
pthread_t *thread_id = &(chn_ctrl->thread_id);
csi_camera_channel_cfg_s *chn_cfg = &(chn_ctrl->chn_cfg);
chn_ctrl->run = true;
chn_ctrl->cam_handle = cam_handle;
chn_cfg->frm_cnt = 4;
if (i = 0) {
chn_cfg->chn_id = CSI_CAMERA_CHANNEL_0;
chn_cfg->img_fmt.width = 640;
chn_cfg->img_fmt.height = 480;
chn_cfg->img_fmt.pix_fmt = CSI_PIX_FMT_NV12;
} else {
chn_cfg->chn_id = CSI_CAMERA_CHANNEL_1;
chn_cfg->img_fmt.width = 1280;
chn_cfg->img_fmt.height = 720;
chn_cfg->img_fmt.pix_fmt = CSI_PIX_FMT_I420;
}
chn_cfg->meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
chn_cfg->capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
CSI_CAMERA_CHANNEL_CAPTURE_META;
pthread_create(thread_id, NULL, channel_thread, chn_ctrl);
sleep(1); // channel[1] start after 1 second
}
sleep(3);
channel_control[0].run = false;
sleep(2);
channel_control[1].run = false;
for (int i = 0; i < 2; i++) {
cam_channel_control_t *chn_ctrl = &channel_control[i];
int chn_id = chn_ctrl->chn_cfg.chn_id;
if (pthread_join(chn_ctrl->thread_id, NULL)) {
LOG_E("[chn-%d] pthread_join() failed, %s\n", chn_id, strerror(errno));
}
}
csi_camera_close(cam_handle);
return 0;
}
static void *channel_thread(void *arg)
{
int ret;
cam_channel_control_t *chn_ctrl = (cam_channel_control_t *)arg;
csi_cam_handle_t cam_handle = chn_ctrl->cam_handle;
int chn_id = chn_ctrl->chn_cfg.chn_id;
ret = csi_camera_channel_open(cam_handle, &(chn_ctrl->chn_cfg));
if (ret != 0) {
LOG_E("[chn_%d] csi_camera_channel_open() failed, ret=%d\n", chn_id, ret);
return NULL;
}
LOG_O("[chn_%d] csi_camera_channel_open() OK\n", chn_id);
// 订阅Event
csi_cam_event_handle_t event_handle;
csi_camera_create_event(&event_handle, cam_handle);
struct csi_camera_event_subscription subscribe_cam;
struct csi_camera_event_subscription subscribe_chn;
subscribe_cam.type = CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
subscribe_cam.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
csi_camera_subscribe_event(event_handle, &subscribe_cam);
subscribe_chn.type = chn_id; // 订阅Channel0的FRAME_READY事件
subscribe_chn.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
csi_camera_subscribe_event(event_handle, &subscribe_chn);
LOG_O("Event subscript OK\n");
// 处理订阅的Event
LOG_O("[chn_%d] Starting get events...\n", chn_id);
csi_frame_s frame;
struct csi_camera_event event;
while (chn_ctrl->run) {
int timeout = 100; // unit: ms, -1 means wait forever, or until error occurs
LOG_D("[chn_%d] before csi_camera_get_event\n", chn_id);
csi_camera_get_event(event_handle, &event, timeout);
LOG_D("[chn_%d] after csi_camera_get_event\n", chn_id);
switch (event.type) {
case CSI_CAMERA_EVENT_TYPE_CAMERA:
switch (event.id) {
case CSI_CAMERA_EVENT_ERROR:
// do sth.
break;
default:
break;
}
case CSI_CAMERA_EVENT_TYPE_CHANNEL0:
case CSI_CAMERA_EVENT_TYPE_CHANNEL1:
if (event.type != chn_id) {
LOG_E("[chn_%d] Recv type(%d) is not expected\n",
chn_id, event.type);
break;
}
switch (event.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
LOG_O("[chn_%d] Get ready frame\n", chn_id);
int read_frame_count = csi_camera_get_frame_count(cam_handle, chn_id);
for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(cam_handle, chn_id, &frame, timeout);
dump_camera_meta(&frame);
csi_camera_put_frame(&frame);
}
break;
}
default:
LOG_W("[chn_%d] Get unknown event type\n", event.type);
break;
}
default:
break;
}
}
csi_camera_unsubscribe_event(event_handle, &subscribe_cam);
csi_camera_unsubscribe_event(event_handle, &subscribe_chn);
csi_camera_destory_event(event_handle);
csi_camera_channel_stop(cam_handle, chn_id);
pthread_exit(NULL);
}
static void dump_camera_meta(csi_frame_s *frame)
{
int i;
if (frame->meta.type != CSI_META_TYPE_CAMERA)
return;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
int meta_count = meta_data->count;
csi_camrea_meta_unit_s meta_unit;
for (i = 0; i < meta_count; i++) {
csi_camera_frame_get_meta_unit(
&meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
printf("meta_id=%d, meta_type=%d, meta_value=%d",
meta_unit.id, meta_unit.type, meta_unit.int_value);
}
}

View File

@@ -0,0 +1,438 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: ShenWuYi <shenwuyi.swy@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <syslog.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <csi_camera.h>
#include <stdlib.h>
#include "process_linker_types.h"
#include "process_linker.h"
#include "video_mem.h"
#define NUM_OF_BUFFERS 5
typedef struct _CsiPictureBuffer
{
unsigned int bus_address;
void *virtual_address;
unsigned int size;
int fd;
} CsiPictureBuffer;
typedef struct _CsiPlinkContext
{
int useplink;
int exitplink;
CsiPictureBuffer sendbuffer[NUM_OF_BUFFERS];
int sendid;
int available_bufs;
void *vmem;
PlinkHandle plink;
PlinkChannelID chnid;
} CsiPlinkContext;
static int get_buffer_count(PlinkPacket *pkt)
{
int ret = 0;
for (int i = 0; i < pkt->num; i++)
{
PlinkDescHdr *hdr = (PlinkDescHdr *)(pkt->list[i]);
if (hdr->type == PLINK_TYPE_MESSAGE)
{
int *data = (int *)(pkt->list[i] + DATA_HEADER_SIZE);
if (*data == PLINK_EXIT_CODE)
{
ret |= 0x80000000; // set bit 31 to 1 to indicate 'exit'
}
else if (*data >= 0)
ret++;
}
}
return ret;
}
static void allocate_sendbuffers(CsiPictureBuffer picbuffers[NUM_OF_BUFFERS], unsigned int size, void *vmem)
{
unsigned int buffer_size = (size + 0xFFF) & ~0xFFF;
VmemParams params;
params.size = buffer_size;
params.flags = VMEM_FLAG_CONTIGUOUS | VMEM_FLAG_4GB_ADDR;
for (int i = 0; i < NUM_OF_BUFFERS; i++)
{
VMEM_allocate(vmem, &params);
VMEM_mmap(vmem, &params);
VMEM_export(vmem, &params);
LOG_O("[SERVER] mmap %p from %x with size %d, dma-buf fd %d\n",
params.vir_address, params.phy_address, params.size, params.fd);
picbuffers[i].virtual_address = params.vir_address;
picbuffers[i].bus_address = params.phy_address;
picbuffers[i].size = buffer_size;
picbuffers[i].fd = params.fd;
}
}
void *vi_plink_create(csi_camera_channel_cfg_s *chn_cfg)
{
int ret = 0;
CsiPlinkContext *plink_ctx = NULL;
char *env=NULL;
if (chn_cfg == NULL) {
LOG_E("%s failt to get chn_cfg\n", __func__);
return NULL;
}
plink_ctx = malloc(sizeof(CsiPlinkContext));
if(!plink_ctx)
{
LOG_E("malloc faile\n");
return NULL;
}
char *plinknamebase0 = "/tmp/plink.test";
char *plinknamebase1 = "/tmp/plink_npu_rgb.test";
char *plinknamebase2 = "/tmp/plink.test2";
env = getenv("ISP_PLINK_NAME0");
if (env != NULL) {
plinknamebase0 = env;
}
env = getenv("ISP_PLINK_NAME1");
if (env != NULL) {
plinknamebase1 = env;
}
env = getenv("ISP_PLINK_NAME2");
if (env != NULL) {
plinknamebase2 = env;
}
char plinkname[32];
if (chn_cfg->chn_id == CSI_CAMERA_CHANNEL_0) {
sprintf(plinkname, "%s", plinknamebase0);
} else if (chn_cfg->chn_id == CSI_CAMERA_CHANNEL_1) {
sprintf(plinkname, "%s", plinknamebase1);
} else {
sprintf(plinkname, "%s", plinknamebase2);
}
fprintf(stderr, "%s, %d: ISP_PLINK_NAME = %s\n", __func__, __LINE__, plinkname);
plink_ctx->exitplink = 0;
fprintf(stderr, "%s, %d: Launching plink server...\n", __func__, __LINE__);
memset(&plink_ctx->sendbuffer[0], 0, sizeof(plink_ctx->sendbuffer));
if (VMEM_create(&plink_ctx->vmem) != VMEM_STATUS_OK)
{
fprintf(stderr, "Failed to create VMEM.");
return NULL;
}
else {
int framesize = 0;
int stride = (chn_cfg->img_fmt.width + 127) & (~127); // align stride to 128
switch (chn_cfg->img_fmt.pix_fmt) {
case CSI_PIX_FMT_BGR:
{
framesize = stride * 304 * 3; //stride * chn_cfg->img_fmt.height * 3;
allocate_sendbuffers(plink_ctx->sendbuffer, framesize, plink_ctx->vmem);
// reset to black picture
uint32_t lumasize = stride * chn_cfg->img_fmt.height;
for (int i = 0; i < NUM_OF_BUFFERS; i++)
memset(plink_ctx->sendbuffer[i].virtual_address, 0, framesize);
break;
}
case CSI_PIX_FMT_NV12:
default:
{
framesize = stride * chn_cfg->img_fmt.height * 3 / 2;
allocate_sendbuffers(plink_ctx->sendbuffer, framesize, plink_ctx->vmem);
// reset to black picture
uint32_t lumasize = stride * chn_cfg->img_fmt.height;
for (int i = 0; i < NUM_OF_BUFFERS; i++) {
CsiPictureBuffer *buf = &plink_ctx->sendbuffer[i];
memset(buf->virtual_address, 0, lumasize);
memset(buf->virtual_address + lumasize, 0x80, lumasize/2);
}
break;
}
}
}
PLINK_create(&plink_ctx->plink, plinkname, PLINK_MODE_SERVER);
if (plink_ctx->plink) {
PLINK_connect(plink_ctx->plink, &plink_ctx->chnid);
}
plink_ctx->sendid = 0;
plink_ctx->available_bufs = NUM_OF_BUFFERS;
return plink_ctx;
}
void vi_plink_release(void * plink)
{
CsiPlinkContext * plink_ctx = (CsiPlinkContext *)plink;
if(plink_ctx)
{
PLINK_close(plink_ctx->plink,plink_ctx->chnid);
VMEM_destroy(plink_ctx->vmem);
}
}
void display_camera_frame(void *plink, csi_frame_s *frame)
{
CsiPlinkContext * plink_ctx = (CsiPlinkContext *)plink;
if ((plink_ctx == NULL) || (frame == NULL)) {
LOG_E("%s check param fail\n", __func__);
return;
}
LOG_O("%sfmt=%d img.strides[0] = %d\n", __func__,frame->img.pix_format, frame->img.strides[0]);
if (!plink_ctx->exitplink) {
struct timeval tv_start, tv_end, tv_duration;
gettimeofday(&tv_start, 0);
// retrieve buffers
PlinkPacket pkt = {0};
if (plink_ctx->plink != NULL) {
while (PLINK_wait(plink_ctx->plink, plink_ctx->chnid, 0) == PLINK_STATUS_OK)
{
if (PLINK_recv(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK) {
plink_ctx->exitplink = 1;
break;
}
int count = get_buffer_count(&pkt);
if (count >= 0)
plink_ctx->available_bufs += count;
else {
fprintf(stderr, "[SERVER] Exit!\n");
plink_ctx->exitplink = 1;
break;
}
}
}
/*
void *phy_address = NULL;
int dmabuf_fd = -1;
if (vi_mem_dmabuf_isenable()) {
phy_address = vi_mem_unmap(frame->img.usr_addr[0]);
dmabuf_fd = vi_mem_export(phy_address);
}
*/
// send one buffer if there is available slot
if (frame->img.type == CSI_IMG_TYPE_DMA_BUF && !plink_ctx->exitplink
&& plink_ctx->available_bufs > 0 && plink_ctx->plink != NULL && ((frame->img.pix_format == CSI_PIX_FMT_RAW_8BIT)|| (frame->img.pix_format == CSI_PIX_FMT_RAW_12BIT))) {
char str[200];
static int i = 0;
uint32_t dstw = frame->img.width;//800;
uint32_t dsth = frame->img.height;//1280;
uint32_t dsts = frame->img.strides[0];//896;
i++;
sprintf(str, "echo frame is %d > ~/frame", i);
system(str);
PlinkRawInfo info = {0};
info.header.type = PLINK_TYPE_2D_RAW;
info.header.size = DATA_SIZE(info);
info.header.id = plink_ctx->sendid + 1;
info.format = PLINK_COLOR_FormatRawBayer10bit;
// info.bus_address = vi_mem_import(frame->img.dmabuf[0].fds) + frame->img.dmabuf[0].offset;
// vi_mem_release(info.bus_address);
info.img_width = dstw;
info.img_height = dsth;
info.stride = frame->img.strides[0];
info.offset = 0;
pkt.list[0] = &info;
pkt.num = 1;
pkt.fd = frame->img.dmabuf[0].fds;
if (PLINK_send(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK)
plink_ctx->exitplink = 1;
gettimeofday(&tv_end, 0);
timersub(&tv_end, &tv_start, &tv_duration);
plink_ctx->sendid = (plink_ctx->sendid + 1) % NUM_OF_BUFFERS;
plink_ctx->available_bufs -= 1;
}
else if (frame->img.type == CSI_IMG_TYPE_DMA_BUF && !plink_ctx->exitplink
&& plink_ctx->available_bufs > 0 && plink_ctx->plink != NULL && ((frame->img.pix_format == CSI_PIX_FMT_YUV_SEMIPLANAR_420)|| (frame->img.pix_format == CSI_PIX_FMT_NV12))) {
char str[200];
static int i = 0;
uint32_t dstw = frame->img.width;//800;
uint32_t dsth = frame->img.height;//1280;
uint32_t dsts = frame->img.strides[0];//896;
i++;
sprintf(str, "echo frame is %d > ~/frame", i);
system(str);
PlinkYuvInfo info = {0};
info.header.type = PLINK_TYPE_2D_YUV;
info.header.size = DATA_SIZE(info);
info.header.id = plink_ctx->sendid + 1;
info.format = PLINK_COLOR_FormatYUV420SemiPlanar;
// info.bus_address_y = vi_mem_import(frame->img.dmabuf[0].fds) + frame->img.dmabuf[0].offset;
// info.bus_address_u = info.bus_address_y + frame->img.dmabuf[1].offset;
// vi_mem_release(info.bus_address_y);
info.pic_width = dstw;
info.pic_height = dsth;
info.stride_y = dsts;
info.stride_u = dsts;
info.stride_v = dsts;
info.offset_y = 0;
info.offset_u = frame->img.dmabuf[1].offset;
info.offset_v = frame->img.dmabuf[2].offset;
pkt.list[0] = &info;
pkt.num = 1;
pkt.fd = frame->img.dmabuf[0].fds;
if (PLINK_send(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK)
plink_ctx->exitplink = 1;
gettimeofday(&tv_end, 0);
timersub(&tv_end, &tv_start, &tv_duration);
plink_ctx->sendid = (plink_ctx->sendid + 1) % NUM_OF_BUFFERS;
plink_ctx->available_bufs -= 1;
} else if (!plink_ctx->exitplink && plink_ctx->available_bufs > 0 && plink_ctx->plink != NULL && (frame->img.pix_format == CSI_PIX_FMT_BGR)) {
CsiPictureBuffer *buf = &plink_ctx->sendbuffer[plink_ctx->sendid];
int y = 0;
uint8_t *src = frame->img.usr_addr[0];
uint8_t *dst = buf->virtual_address;
uint32_t srcw = frame->img.width;
uint32_t srch = frame->img.height;
uint32_t dstw = frame->img.width;
uint32_t dsth = frame->img.height;
uint32_t dsts = frame->img.width;
switch (frame->img.pix_format ) {
case CSI_PIX_FMT_BGR:
{
dstw = 300;
dsth = 304;
uint32_t w = dstw > srcw ? srcw : dstw;
uint32_t h = dsth > srch ? srch : dsth;
if (w != 300 || h != 176 || dsts != 304) {
fprintf(stderr, "ERROR: expect 300x300 (stride 304) image while recieved %dx%d (stride %d) image\n", w, h, dsts);
break;
}
for (y = 0; y < h; y++)
{
memcpy(dst, src, w);
src += srcw;
dst += dsts;
}
src = frame->img.usr_addr[0] + srcw*srch;
dst = buf->virtual_address + dsts*dsth;
for (y = 0; y < h; y++)
{
memcpy(dst, src, w);
src += srcw;
dst += dsts;
}
src = frame->img.usr_addr[0] + srcw*srch*2;
dst = buf->virtual_address + dsts*dsth*2;
for (y = 0; y < h; y++)
{
memcpy(dst, src, w);
src += srcw;
dst += dsts;
}
PlinkRGBInfo info = {0};
info.header.type = PLINK_TYPE_2D_RGB;
info.header.size = DATA_SIZE(info);
info.header.id = plink_ctx->sendid + 1;
info.format = PLINK_COLOR_Format24BitBGR888Planar;
info.bus_address_b = buf->bus_address;
info.bus_address_g = info.bus_address_b + dsts*dsth;
info.bus_address_r = info.bus_address_g + dsts*dsth;
info.img_width = dstw;
info.img_height = dsth;
info.stride_b = dsts;
info.stride_g = dsts;
info.stride_r = dsts;
pkt.list[0] = &info;
pkt.num = 1;
pkt.fd = buf->fd;
if (PLINK_send(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK)
plink_ctx->exitplink = 1;
break;
}
case CSI_PIX_FMT_NV12:
default:
{
uint32_t w = dstw > srcw ? srcw : dstw;
uint32_t h = dsth > srch ? srch : dsth;
for (y = 0; y < h; y++)
{
memcpy(dst, src, w);
src += srcw;
dst += dsts;
}
src = frame->img.usr_addr[0] + frame->img.strides[0] * frame->img.height;
dst = buf->virtual_address + (dsts * dsth);
for (y = 0; y < h/2; y++)
{
memcpy(dst, src, w);
src += srcw;
dst += dsts;
}
PlinkYuvInfo info = {0};
info.header.type = PLINK_TYPE_2D_YUV;
info.header.size = DATA_SIZE(info);
info.header.id = plink_ctx->sendid + 1;
info.format = PLINK_COLOR_FormatYUV420SemiPlanar;
info.bus_address_y = buf->bus_address;
info.bus_address_u = buf->bus_address + dsts*dsth;
info.bus_address_v = info.bus_address_u;
info.pic_width = dstw;
info.pic_height = dsth;
info.stride_y = dsts;
info.stride_u = dsts;
info.stride_v = dsts;
pkt.list[0] = &info;
pkt.num = 1;
pkt.fd = buf->fd;
if (PLINK_send(plink_ctx->plink, plink_ctx->chnid, &pkt) != PLINK_STATUS_OK)
plink_ctx->exitplink = 1;
break;
}
}
gettimeofday(&tv_end, 0);
timersub(&tv_end, &tv_start, &tv_duration);
plink_ctx->sendid = (plink_ctx->sendid + 1) % NUM_OF_BUFFERS;
plink_ctx->available_bufs -= 1;
}
}
LOG_O("%s exit \n", __func__);
}

391
examples/camera/camera_test1.c Executable file
View File

@@ -0,0 +1,391 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LOG_LEVEL 2
#define LOG_PREFIX "camera_demo1"
#include <syslog.h>
#include <csi_frame.h>
#include <csi_camera.h>
#ifdef PLATFORM_SIMULATOR
#include "apputilities.h"
#endif
static void dump_camera_meta(csi_frame_s *frame);
static int save_camera_img(csi_frame_s *frame);
static int save_camera_stream(csi_frame_s *frame);
#define TEST_DEVICE_NAME "/dev/video0"
#define CSI_CAMERA_TRUE 1
#define CSI_CAMERA_FALSE 0
char *prog_name;
void usage()
{
fprintf (stderr,
"usage: %s [options]\n"
"Options:\n"
"\t-D dev target video device like /dev/video0\n"
"\t-R resolution format is like 640x480\n"
"\t-F format like NV12\n"
"\t-C channel_index channel index defined in dts, index from 0\n"
"\t-M output mode 0: save as image; 1: save as stream file\n"
"\t-N number for frames 0: record forever; others: the recorded frame numbers"
, prog_name
);
}
int main(int argc, char *argv[])
{
bool running = false;
csi_camera_info_s camera_info;
int opt;
char device[CSI_CAMERA_NAME_MAX_LEN]; /* target video device like /dev/video0 */
char *resolution; /* resolution information like 640x480 */
int hres, vres; /* resolution information like 640x480 */
char *resDelim = "xX";
char *format; /* format information like NV12 */
enum csi_pixel_fmt fenum;
int channelIdx; /* channel information like 8 */
int outMode = 0;
int fNum = 0;
prog_name = argv[0];
while ((opt = getopt(argc, argv, "D:R:F:C:M:hN:")) != EOF) {
switch(opt) {
case 'D':
//device = optarg;
strcpy(device, optarg);
continue;
case 'R':
resolution = optarg;
hres = atoi(strtok(resolution, resDelim));
vres = atoi(strtok(NULL, resDelim));
continue;
case 'M':
outMode = atoi(optarg);
continue;
case 'N':
fNum = atoi(optarg);
continue;
case 'F':
format = optarg;
if(strstr(format, "NV12")){
fenum = CSI_PIX_FMT_NV12;
}
else if(strstr(format, "I420")){
fenum = CSI_PIX_FMT_I420;
}
else{
fenum = CSI_PIX_FMT_I420;
}
continue;
case 'C':
channelIdx = atoi(optarg);
continue;
case '?':
case 'h':
default:
usage();
return 1;
}
}
const csi_camera_channel_id_e CAMERA_CHANNEL_ID = CSI_CAMERA_CHANNEL_0 + channelIdx;
const csi_camera_event_type_e CAMERA_CHANNEL_EVENT_TYPE = CSI_CAMERA_EVENT_TYPE_CHANNEL0 + channelIdx;
if (fNum == 0)
running == true;
// 打印HAL接口版本号
csi_api_version_u version;
csi_camera_get_version(&version);
printf("Camera HAL version: %d.%d\n", version.major, version.minor);
// 获取设备中所有的Camera
struct csi_camera_infos camera_infos;
memset(&camera_infos, 0, sizeof(camera_infos));
csi_camera_query_list(&camera_infos);
// 打印所有设备所支持的Camera
for (int i = 0; i < camera_infos.count; i++) {
camera_info = camera_infos.info[i];
printf("Camera[%d]: camera_name='%s', device_name='%s', bus_info='%s', capabilities=0x%08x\n",
i,
camera_info.camera_name, camera_info.device_name, camera_info.bus_info,
camera_info.capabilities);
printf("Camera[%d] caps are:\n",
i); /* The caps are: Video capture, metadata capture */
for (int j = 1; j <= 0x08000000; j = j << 1) {
switch (camera_info.capabilities & j) {
case CSI_CAMERA_CAP_VIDEO_CAPTURE:
printf("\t camera_infos.info[%d]:Video capture,\n", i);
break;
case CSI_CAMERA_CAP_META_CAPTURE:
printf("\t camera_infos.info[%d] metadata capture,\n", i);
break;
default:
if (camera_info.capabilities & j) {
printf("\t camera_infos.info[%d] unknown capabilities(0x%08x)\n", i,
camera_info.capabilities & j);
}
break;
}
}
}
// 打开Camera设备获取句柄作为后续操对象
csi_cam_handle_t cam_handle;
//csi_camera_open(&cam_handle, camera_info.device_name);
strcpy(camera_info.device_name, device);
//camera_info.device_name = device;
csi_camera_open(&cam_handle, camera_info.device_name);
//csi_camera_open(&cam_handle, device);
// 获取Camera支持的工作模式
struct csi_camera_modes camera_modes;
csi_camera_get_modes(cam_handle, &camera_modes);
// 打印camera所支持的所有工作模式
printf("Camera:'%s' modes are:\n", device);
printf("{\n");
for (int i = 0; i < camera_modes.count; i++) {
printf("\t mode_id=%d: description:'%s'\n",
camera_modes.modes[i].mode_id, camera_modes.modes[i].description);
}
printf("}\n");
// 设置camera的工作模式及其配置
csi_camera_mode_cfg_s camera_cfg;
camera_cfg.mode_id = 1;
camera_cfg.calibriation = NULL; // 采用系统默认配置
camera_cfg.lib3a = NULL; // 采用系统默认配置
csi_camera_set_mode(cam_handle, &camera_cfg);
// 获取单个可控单元的属性
csi_camera_property_description_s description;
/* id=0x0098090x, type=2 default=0 value=1 */
/* Other example:
* id=0x0098090y, type=3 min=0 max=255 step=1 default=127 value=116
* id=0x0098090z, type=4 min=0 max=3 default=0 value=2
* 0: IDLE
* 1: BUSY
* 2: REACHED
* 3: FAILED
*/
// 轮询获取所有可控制的单元
printf("all properties are:\n");
description.id = CSI_CAMERA_PID_HFLIP;
while (!csi_camera_query_property(cam_handle, &description)) {
switch (description.type) {
case (CSI_CAMERA_PROPERTY_TYPE_INTEGER):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.int_value, description.value.int_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BOOLEAN):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.bool_value, description.value.bool_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_ENUM):
printf("id=0x%08x type=%d default=%d value=%d\n",
description.id, description.type,
description.default_value.enum_value, description.value.enum_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_STRING):
printf("id=0x%08x type=%d default=%s value=%s\n",
description.id, description.type,
description.default_value.str_value, description.value.str_value);
break;
case (CSI_CAMERA_PROPERTY_TYPE_BITMASK):
printf("id=0x%08x type=%d default=%x value=%x\n",
description.id, description.type,
description.default_value.bitmask_value, description.value.bitmask_value);
break;
default:
LOG_E("error type!\n");
break;
}
description.id |= CSI_CAMERA_FLAG_NEXT_CTRL;
}
// 同时配置多个参数
csi_camera_properties_s properties;
csi_camera_property_s property[3];
property[0].id = CSI_CAMERA_PID_HFLIP;
property[0].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
property[0].value.bool_value = false;
property[1].id = CSI_CAMERA_PID_VFLIP;
property[1].type = CSI_CAMERA_PROPERTY_TYPE_BOOLEAN;
property[1].value.bool_value = false;
property[2].id = CSI_CAMERA_PID_ROTATE;
property[2].type = CSI_CAMERA_PROPERTY_TYPE_INTEGER;
property[2].value.int_value = 0;
properties.count = 3;
properties.property = property;
if (csi_camera_set_property(cam_handle, &properties) < 0) {
LOG_O("set_property fail!\n");
}
LOG_O("set_property ok!\n");
// 查询输出channel
csi_camera_channel_cfg_s chn_cfg;
chn_cfg.chn_id = CAMERA_CHANNEL_ID;
csi_camera_channel_query(cam_handle, &chn_cfg);
if (chn_cfg.status != CSI_CAMERA_CHANNEL_CLOSED) {
printf("Can't open CSI_CAMERA_CHANNEL_0\n");
exit(-1);
}
// 打开输出channel
chn_cfg.chn_id = channelIdx;
chn_cfg.frm_cnt = 4;
chn_cfg.img_fmt.width = hres;
chn_cfg.img_fmt.height = vres;
chn_cfg.img_fmt.pix_fmt = fenum;
chn_cfg.img_type = CSI_IMG_TYPE_DMA_BUF;
chn_cfg.meta_fields = CSI_CAMERA_META_DEFAULT_FIELDS;
chn_cfg.capture_type = CSI_CAMERA_CHANNEL_CAPTURE_VIDEO |
CSI_CAMERA_CHANNEL_CAPTURE_META;
csi_camera_channel_open(cam_handle, &chn_cfg);
// 订阅Event
csi_cam_event_handle_t event_handle;
csi_camera_create_event(&event_handle, cam_handle);
csi_camera_event_subscription_s subscribe;
subscribe.type =
CSI_CAMERA_EVENT_TYPE_CAMERA; // 订阅Camera的ERROR事件
subscribe.id = CSI_CAMERA_EVENT_WARNING | CSI_CAMERA_EVENT_ERROR;
csi_camera_subscribe_event(event_handle, &subscribe);
subscribe.type =
CAMERA_CHANNEL_EVENT_TYPE; // 订阅Channel0的FRAME_READY事件
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY |
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW;
csi_camera_subscribe_event(event_handle, &subscribe);
// 开始从channel中取出准备好的frame
csi_camera_channel_start(cam_handle, CAMERA_CHANNEL_ID);
// 处理订阅的Event
csi_frame_s frame;
struct csi_camera_event event;
while (running || fNum >= 0 ) {
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
csi_camera_get_event(event_handle, &event, timeout);
if(event.type == CSI_CAMERA_EVENT_TYPE_CAMERA){
switch (event.id) {
case CSI_CAMERA_EVENT_ERROR:
// do sth.
LOG_D("get CAMERA EVENT CSI_CAMERA_EVENT_ERROR!\n");
break;
default:
break;
}
}
if(event.type == CAMERA_CHANNEL_EVENT_TYPE){
switch (event.id) {
case CSI_CAMERA_CHANNEL_EVENT_FRAME_READY: {
int read_frame_count = csi_camera_get_frame_count(cam_handle,
CAMERA_CHANNEL_ID);
for (int i = 0; i < read_frame_count; i++) {
csi_camera_get_frame(cam_handle, CAMERA_CHANNEL_ID, &frame, timeout);
fNum--;
#ifdef PLATFORM_SIMULATOR
show_frame_image(frame.img.usr_addr[0], frame.img.height, frame.img.width);
#endif
if (outMode == 0)
save_camera_img(&frame);
else
save_camera_stream(&frame);
csi_frame_release(&frame);
}
break;
}
default:
break;
}
}
}
csi_camera_channel_stop(cam_handle, CAMERA_CHANNEL_ID);
usleep (1000000);
// 取消订阅某一个event, 也可以直接调用csi_camera_destory_event结束所有的订阅
subscribe.type = CAMERA_CHANNEL_EVENT_TYPE;
subscribe.id = CSI_CAMERA_CHANNEL_EVENT_FRAME_READY;
csi_camera_unsubscribe_event(event_handle, &subscribe);
csi_camera_destory_event(event_handle);
csi_camera_channel_close(cam_handle, CAMERA_CHANNEL_ID);
csi_camera_close(cam_handle);
}
static void dump_camera_meta(csi_frame_s *frame)
{
int i;
//printf("%s\n", __func__);
if (frame->meta.type != CSI_META_TYPE_CAMERA)
return;
csi_camera_meta_s *meta_data = (csi_camera_meta_s *)frame->meta.data;
int meta_count = meta_data->count;
csi_camrea_meta_unit_s meta_unit;
for (i = 0; i < meta_count; i++) {
csi_camera_frame_get_meta_unit(
&meta_unit, meta_data, CSI_CAMERA_META_ID_FRAME_ID);
//printf("meta_id=%d, meta_type=%d, meta_value=%d",
// meta_unit.id, meta_unit.type, meta_unit.int_value);
}
}
static int save_camera_img(csi_frame_s *frame)
{
static int fcount = 0;
char fname[20];
FILE *fp;
fcount = fcount%4;
sprintf(fname, "%s%d%s", "hal_image", fcount, ".yuv");
fcount++;
if((fp = fopen(fname, "wb")) == NULL){
printf("Error: Can't open file\n");
return -1;
}
fwrite(frame->img.usr_addr[0], sizeof(char), frame->img.size, fp);
fclose(fp);
return 0;
}
static int save_camera_stream(csi_frame_s *frame)
{
FILE *fp;
char *fname = "hal_stream.yuv";
if((fp = fopen(fname, "ab+")) == NULL){
printf("Error: Can't open file\n");
return -1;
}
fwrite(frame->img.usr_addr[0], sizeof(char), frame->img.size, fp);
fclose(fp);
return 0;
}

View File

@@ -0,0 +1,41 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
DIR_TO_ROOT=../../..
include $(DIR_TO_ROOT)/build.param
LIBOPENCV_INC = $(shell pkg-config --cflags opencv) -I./
LIBOPENCV_LIBS = $(shell pkg-config --libs opencv)
TARGET := libapp_utilities.a
OUTPUT_DIR := $(DIR_TO_ROOT)/output/hal/
#CFLAGS = -Wall -g -O0
SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o)
all: $(TARGET)
$(TARGET): $(OBJS)
@mkdir -p $(OUTPUT_DIR)
@echo "Linking" $@ "..."
$(AR) -r -o $(OUTPUT_DIR)/$@ .obj/*.o
$(OBJS): %.o:%.cpp
@echo $(BUILD_LOG_START)
@mkdir -p .obj
@echo "Compiling" $< "..."
$(CXX) $(CFLAGS) $(INCLUDE) $(LIBOPENCV_INC) $(LIBOPENCV_LIBS) -c -o .obj/$(notdir $@) $<
@echo $(BUILD_LOG_END)
clean:
rm -rf .obj
rm -f $(OUTPUT_DIR)/$(TARGET)
.PHONY: clean all

View File

@@ -0,0 +1,24 @@
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
#include "apputilities.h"
int show_frame_image(void *mat, int height, int width)
{
Mat dis_mat;
dis_mat.create(height * 3 / 2, width, CV_8UC1);
dis_mat.data = (uchar *)mat;
cvtColor(dis_mat, dis_mat, CV_YUV2BGRA_I420);
namedWindow("camera local i420");
imshow("camera local i420", dis_mat);
waitKey(1);
dis_mat.release();
return 0;
}

View File

@@ -0,0 +1,16 @@
#ifndef __APPUTILITIES_H__
#define __APPUTILITIES_H__
#ifdef __cplusplus
extern "C" {
#endif
//wait for complete
int show_frame_image(void *mat, int height, int width);
#ifdef __cplusplus
};
#endif
#endif

View File

@@ -0,0 +1,3 @@
#!/bin/bash
# To watch log output, use: tail -f /tmp/debug_camera_demo3.log
stdbuf -oL ./camera_demo3 >> /tmp/debug_camera_demo3.log 2>&1

1
examples/common/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
mtrace_demo

27
examples/common/Makefile Normal file
View File

@@ -0,0 +1,27 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
DIR_TO_ROOT=../..
include $(DIR_TO_ROOT)/build.param
#CFLAGS +=
LIBS += -lhal_common
OUTPUT_DIR := $(DIR_TO_ROOT)/output/examples/common
TARGET_1 := mtrace_demo
SRCS_1 = mtrace_demo.c
all: $(TARGET_1)
clean:
rm -rf .obj
rm -f $(TARGET_1) $(OUTPUT_DIR)/$(TARGET_1)
include $(DIR_TO_ROOT)/common_target.mk
.PHONY: clean all

View File

@@ -0,0 +1,25 @@
#define DEBUG_MTRACE
#include <stdlib.h> // for malloc
#include <mcheck.h> // for mtrace() / muntrace();
#define LOG_LEVEL 2
#include <syslog.h>
int main(int argc, char **argv)
{
LOG_I("Enter\n");
int ret;
#ifdef DEBUG_MTRACE
mtrace();
#endif
int *tmp = malloc(0x1234);
LOG_I("malloc 0x1234 bytes(%p) without free.\n", tmp);
#ifdef DEBUG_MTRACE
muntrace();
#endif
LOG_I("Exit\n");
}

View File

@@ -0,0 +1,13 @@
#!/bin/sh
export MALLOC_TRACE=/tmp/mtrace_demo_mtrace.log
rm -f $MALLOC_TRACE
# set '/proc/sys/kernel/randomize_va_space' to be 0
# to disable Address Space Layout Randomization(ASLR)
#sudo sysctl -w kernel.randomize_va_space=0
echo "\n**** Run mtrace demo ****"
./mtrace_demo
echo "\n**** mtrace analysis result ****"
mtrace ./mtrace_demo $MALLOC_TRACE | grep -E "\.c|\.cpp"

3
examples/frame/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
frame_demo1
frame_demo2
consumer_dump_file.yuv

33
examples/frame/Makefile Normal file
View File

@@ -0,0 +1,33 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
DIR_TO_ROOT=../..
include $(DIR_TO_ROOT)/build.param
CFLAGS += -I$(DIR_TO_ROOT)/src/platform/simulator/drivers/ion/
LIBS += -lhal_common -lhal_platform
OUTPUT_DIR := $(DIR_TO_ROOT)/output/examples/frame
TARGET_1 := frame_demo1
SRCS_1 = frame_demo1.c frame_demo_common.c
TARGET_2 := frame_demo2
SRCS_2 = frame_demo2.c frame_demo2_producer.c frame_demo2_consumer.c frame_demo_common.c
all: $(TARGET_1) $(TARGET_2)
@mkdir -p $(OUTPUT_DIR)/../resource
cp -f $(DIR_TO_ROOT)/examples/resource/yuv420_1280x720_csky2016.yuv $(OUTPUT_DIR)/../resource
clean:
rm -rf .obj
rm -f $(TARGET_1) $(OUTPUT_DIR)/$(TARGET_1)
rm -f $(TARGET_2) $(OUTPUT_DIR)/$(TARGET_2)
include $(DIR_TO_ROOT)/common_target.mk
.PHONY: clean all

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#define LOG_LEVEL 2
#define LOG_PREFIX "camera_demo1"
#include <syslog.h>
#include <ion.h>
#include <csi_frame.h>
#include <csi_camera_frame.h>
#include "frame_demo_common.h"
static const char *img_name = "../resource/yuv420_1280x720_csky2016.yuv";
static csi_img_format_t img_format = {
.width = 1280,
.height = 720,
.pix_fmt = CSI_PIX_FMT_I420,
};
int main(int argc, char *argv[])
{
int ret = -1;
int i;
int img_fd;
long img_size;
int ion_fd;
int dmabuf_fd;
void *dmabuf_addr;
csi_frame_s camera_frame;
csi_camera_meta_s *camera_meta;
// get image file size
if (fdc_get_img_file_size(&img_size, img_name) != 0)
goto LAB_ERR;
// open ion device
if (fdc_get_ion_device_fd(&ion_fd) != 0)
goto LAB_ERR;
// alloc dma-buf from ion device
struct ion_allocation_data alloc_data;
if (fdc_alloc_ion_buf(&alloc_data, ion_fd, img_size) != 0)
goto LAB_ERR_ION_OPENED;
dmabuf_fd = alloc_data.fd;
// map dma-buf to user addr
if (fdc_mmap_dmabuf_addr(&dmabuf_addr, img_size, dmabuf_fd) != 0)
goto LAB_ERR_BUF_ALLOCED;
// open image file
img_fd = open(img_name, O_RDONLY);
if (img_fd < 0) {
LOG_E("Open image file '%s' failed, %s\n",
img_name, strerror(errno));
goto LAB_ERR_MMAPPED;
}
// store image into dma-buf
if (fdc_store_img_to_dmabuf(dmabuf_addr, img_fd, img_size) != 0)
goto LAB_ERR_IMG_OPENED;
// create csi_frame
if (fdc_create_csi_frame(&camera_frame, &img_format, &camera_meta, img_size, dmabuf_fd,
dmabuf_addr) != 0)
goto LAB_ERR_IMG_OPENED;
// dump camera meta from csi frame
fdc_dump_camera_meta((csi_camera_meta_s *)camera_frame.meta.data);
// destory csi_frame
fdc_destory_csi_frame(&camera_frame);
ret = 0;
LAB_ERR_IMG_OPENED:
close(img_fd);
LAB_ERR_MMAPPED:
munmap(dmabuf_addr, img_size);
LAB_ERR_BUF_ALLOCED:
close(dmabuf_fd);
LAB_ERR_ION_OPENED:
close(ion_fd);
LAB_ERR:
return ret;
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/socket.h>
#define LOG_LEVEL 2
#define LOG_PREFIX "master"
#include <syslog.h>
#include <ion.h>
#include <csi_frame.h>
#include <csi_camera_frame.h>
#include "frame_demo_common.h"
const char *img_name = "../resource/yuv420_1280x720_csky2016.yuv";
csi_img_format_t img_format = {
.width = 1280,
.height = 720,
.pix_fmt = CSI_PIX_FMT_I420,
};
extern int producer_process(int socket_fd);
extern int consumer_process(int socket_fd);
int main(int argc, char *argv[])
{
int ret;
int socket_pair[2]; /* sockpair() */
pid_t producer_pid;
pid_t consumer_pid;
int process_status; /* the status of child process */
char str_sockfd[10]; /* store the string format */
/* Create socket pare */
if (socketpair(AF_LOCAL, SOCK_STREAM, 0,
socket_pair) == -1) { /* must be AF_LOCAL or AF_UNIX !!!!*/
LOG_E("create socketpair error(%d), %s\n", errno, strerror(errno));
exit(1);
}
LOG_I("Create socketpair OK:{%d, %d}\n", socket_pair[0], socket_pair[1]);
/* run producer process, using socket_pair[0] */
if ((producer_pid = fork()) == 0) {
/* child process2: producer_process */
LOG_D("producer process starting ...\n");
close(socket_pair[1]); // producer only use socket_pair[0]
producer_process(socket_pair[0]);
LOG_D("producer process exiting ...\n");
exit(0);
}
/* run consumer process, using socket_pair[1] */
if ((consumer_pid = fork()) == 0) {
/* child process1: consumer_process */
LOG_D("consumer process starting...\n");
close(socket_pair[0]); // producer only use socket_pair[1]
consumer_process(socket_pair[1]);
LOG_D("consumer process exiting...\n");
exit(0);
}
/* wait the children process end */
waitpid(producer_pid, &process_status, 0);
if (WIFEXITED(process_status) == 0) {
LOG_E("producer exit abnormal\n");
}
waitpid(consumer_pid, &process_status, 0);
if (WIFEXITED(process_status) == 0) {
LOG_E("consumer eixt abnormal\n");
}
/* close the socket_pair */
ret = close(socket_pair[0]);
LOG_D("close(socket_pair[0]) ret=%d, %s\n", errno, strerror(errno));
ret = close(socket_pair[1]);
LOG_D("close(socket_pair[1]) ret=%d, %s\n", errno, strerror(errno));
LOG_D("Exit master\n");
return 0;
}

View File

@@ -0,0 +1,187 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/socket.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "consumer"
#include <syslog.h>
#include <dump_utils.h>
#include <ion.h>
#include <csi_frame.h>
#include <csi_camera_frame.h>
#include "frame_demo_common.h"
extern const char *img_name;
extern csi_img_format_t img_format;
int consumer_process(int socket_fd)
{
int ret = -1;
LOG_D("Starting consumer\n");
sleep(1); // waiting for producer exit to watch log easily
if (socket_fd <= 0) {
LOG_E("socket_fd(%d) is invalid\n", socket_fd);
goto LAB_ERR;
}
LOG_D("The input socket_fd=%d\n", socket_fd);
struct msghdr msghdr_recv = { // init data
.msg_name = NULL, // the socket address
.msg_namelen = 0, // len of socket name
};
char ctrls[CMSG_SPACE(sizeof(int)*3)] = {};
memset(ctrls, 0, sizeof(ctrls));
msghdr_recv.msg_control = ctrls;
msghdr_recv.msg_controllen = sizeof(ctrls);
csi_frame_s camera_frame;
csi_camera_meta_s camera_meta;
char meta_data[CSI_CAMERA_META_MAX_LEN]; //CSI_CAMERA_META_MAX_LEN
struct iovec iov[3];
iov[0].iov_base = &camera_frame.img; // iov[0] stores csi_frame.img info
iov[0].iov_len = sizeof(camera_frame.img);
iov[1].iov_base = &camera_frame.meta; // iov[1] stores csi_frame.meta info
iov[1].iov_len = sizeof(camera_frame.meta);
iov[2].iov_base = meta_data; // iov[2] stores csi_frame.meta data
iov[2].iov_len = sizeof(meta_data);
msghdr_recv.msg_iov = iov; // the io/vector info
msghdr_recv.msg_iovlen = CSI_IMAGE_MAX_PLANES; // the num of iov
ssize_t recv_len;
if ((recv_len = recvmsg(socket_fd, &msghdr_recv, 0)) < 0) {
// the msg is recv by msghdr_recv
LOG_E("recv error:%d, %s\n", errno, strerror(errno));
goto LAB_ERR;
}
LOG_D("recvmsg() length=%zd\n", recv_len);
fdc_dump_msghdr(&msghdr_recv);
int msghdr_count = 0;
struct cmsghdr *pCmsghdr = NULL; // the pointer of control
for (pCmsghdr = CMSG_FIRSTHDR(&msghdr_recv); pCmsghdr != NULL;
pCmsghdr = CMSG_NXTHDR(&msghdr_recv,pCmsghdr)) {
msghdr_count++;
}
LOG_D("msghdr_count=%d\n", msghdr_count);
// now, only 1 plane even in I420 format (CSI_IMAGE_I420_PLANES)
if ((pCmsghdr = CMSG_FIRSTHDR(&msghdr_recv)) != NULL &&
pCmsghdr->cmsg_len == CMSG_LEN(sizeof(int) * 1)) {
if (pCmsghdr->cmsg_level != SOL_SOCKET) {
LOG_E("Ctl level should be SOL_SOCKET\n");
goto LAB_ERR;
}
if (pCmsghdr->cmsg_type != SCM_RIGHTS) {
LOG_E("Ctl type should be SCM_RIGHTS\n");
goto LAB_ERR;
}
int fd_count = (pCmsghdr->cmsg_len - CMSG_SPACE(0)) / sizeof(int);
LOG_D("pCmsghdr->cmsg_len=%zd, fd_count=%d\n", pCmsghdr->cmsg_len, fd_count);
int *fdptr = (int *) CMSG_DATA(pCmsghdr);
for (int i = 0; i < CSI_IMAGE_MAX_PLANES; i ++) {
if (i < fd_count)
camera_frame.img.fds[i] = fdptr[i];
else
camera_frame.img.fds[i] = -1;
}
} else {
if (pCmsghdr == NULL)
LOG_E("pCmsghdr=%p\n", pCmsghdr);
else
LOG_E("pCmsghdr->cmsg_len=%zu, should=%zu\n",
pCmsghdr->cmsg_len,
CMSG_LEN(sizeof(int) * CSI_IMAGE_MAX_PLANES));
goto LAB_ERR;
}
int dma_buf_fd = camera_frame.img.fds[0];
LOG_D("recvmsg() with dmabuf_fds={%d, %d, %d}\n",
camera_frame.img.fds[0], camera_frame.img.fds[1], camera_frame.img.fds[2]);
// fill camera frame img fds
camera_frame.meta.data = meta_data;
csi_dump_hex((char *)(&camera_frame.meta), sizeof(camera_frame.meta), "meta");
csi_dump_hex(camera_frame.meta.data, camera_frame.meta.size, "consumer: meta.data");
csi_dump_img_info(&camera_frame.img);
csi_camera_meta_s *camera_meta_data = (csi_camera_meta_s *)camera_frame.meta.data;
camera_meta_data->units = (csi_camrea_meta_unit_s *)((char *)camera_meta_data + sizeof(csi_camera_meta_s));
fdc_dump_camera_meta(camera_meta_data);
LOG_D("csi frame meta = {type=%d, size=%zd, data=%p}\n",
camera_frame.meta.type, camera_frame.meta.size, camera_frame.meta.data);
LOG_D("csi camera meta = {.count=%d, .size=%zd, .units=%p}\n",
camera_meta_data->count, camera_meta_data->size, camera_meta_data->units);
// save image file
const char *save_file_name = "consumer_dump_file.yuv";
remove(save_file_name);
FILE *dump_file = fopen(save_file_name, "wb");
if (dump_file) {
void *addr = NULL;
int length = 0;
length = camera_frame.img.size; //(img_format.height * img_format.width);
ret = fdc_mmap_dmabuf_addr(&addr, length, camera_frame.img.fds[0]);
LOG_D("ret=%d, addr=%p, lenght=%d\n", ret, addr, length);
if (ret == 0 || addr != NULL) {
size_t write_len = fwrite(addr, length, 1, dump_file);
LOG_O("dump dma-buf into '%s', write_len=%zd\n",
save_file_name, write_len);
}
fclose(dump_file);
} else {
LOG_E("fopen failed, %s\n", strerror(errno));
}
//fclose(dump_file);
for (int i = 0; i < CSI_IMAGE_MAX_PLANES; i++) {
if (camera_frame.img.fds[i] > 0) {
ret = close(camera_frame.img.fds[i]);
LOG_D("close(camera_frame.img.fds[%d]) ret=%d, %s\n",
i, errno, strerror(errno));
}
}
ret = close(socket_fd);
LOG_D("close(socket_fd) ret=%d, %s\n", errno, strerror(errno));
ret = 0;
LAB_ERR:
if (ret)
LOG_E("Exiting consumer\n");
else
LOG_D("Exiting consumer\n");
return ret;
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/socket.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "producer"
#include <syslog.h>
#include <dump_utils.h>
#include <ion.h>
#include <csi_frame.h>
#include <csi_camera_frame.h>
#include "frame_demo_common.h"
extern const char *img_name;
extern csi_img_format_t img_format;
int producer_process(int socket_fd)
{
int ret = -1;
int img_fd;
long img_size;
int ion_fd;
int dmabuf_fd;
void *dmabuf_addr;
csi_frame_s camera_frame;
csi_camera_meta_s *camera_meta;
LOG_D("Starting producer\n");
if (socket_fd <= 0) {
LOG_E("socket_fd(%d) is invalid\n", socket_fd);
goto LAB_EXIT;
}
LOG_D("The input socket_fd=%d\n", socket_fd);
// get image file size
if (fdc_get_img_file_size(&img_size, img_name) != 0)
goto LAB_EXIT;
// open ion device
if (fdc_get_ion_device_fd(&ion_fd) != 0)
goto LAB_EXIT;
// alloc dma-buf from ion device
struct ion_allocation_data alloc_data;
if (fdc_alloc_ion_buf(&alloc_data, ion_fd, img_size) != 0)
goto LAB_ERR_ION_OPENED;
dmabuf_fd = alloc_data.fd;
// map dma-buf to user addr
if (fdc_mmap_dmabuf_addr(&dmabuf_addr, img_size, dmabuf_fd) != 0) // should do unmap!!!!!!!!!!!!!!!!!
goto LAB_ERR_BUF_ALLOCED;
// open image file
img_fd = open(img_name, O_RDONLY);
if (img_fd < 0) {
LOG_E("Open image file '%s' failed, %s\n",
img_name, strerror(errno));
goto LAB_ERR_MMAPPED;
}
// store image into dma-buf
if (fdc_store_img_to_dmabuf(dmabuf_addr, img_fd, img_size) != 0)
goto LAB_ERR_IMG_OPENED;
// create csi_frame
if (fdc_create_csi_frame(&camera_frame, &img_format, &camera_meta,
img_size, dmabuf_fd, dmabuf_addr) != 0)
goto LAB_ERR_IMG_OPENED;
// dump camera meta from csi frame
fdc_dump_camera_meta((csi_camera_meta_s *)camera_frame.meta.data);
csi_dump_hex((char*)camera_meta, camera_frame.meta.size, "producer: meta.data");
csi_dump_img_info(&camera_frame.img);
////////////////////////////////////////////////////////////////////////
// store csi_frame into socket msg and send begin
struct msghdr msghdr_send = { // init data
.msg_name = NULL, // the socket address
.msg_namelen = 0, // len of socket name
};
int transfer_fd_count = 1; // it's YUV420P, has only 2 planes
char ctrls[CMSG_SPACE(sizeof(int)) * CSI_IMAGE_MAX_PLANES] = {}; // store dma-buf fd
msghdr_send.msg_control = ctrls;
msghdr_send.msg_controllen = CMSG_SPACE(sizeof(int)) * transfer_fd_count;
LOG_D("msg_controllen = %zd\n", msghdr_send.msg_controllen);
struct cmsghdr *pCmsghdr; // the pointer of control
int *fdptr = (int *) CMSG_DATA(pCmsghdr);
// the 1st info stores dma-buf fd[0]
pCmsghdr = CMSG_FIRSTHDR(&msghdr_send); // the info of head
pCmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); // the msg len
pCmsghdr->cmsg_level = SOL_SOCKET; // stream mode
pCmsghdr->cmsg_type = SCM_RIGHTS; // file descriptor
fdptr = (int *) CMSG_DATA(pCmsghdr);
*fdptr = camera_frame.img.fds[0];
struct iovec iov[3]; // io vector strores csi_frame
iov[0].iov_base = &camera_frame.img; // iov[0] stores csi_frame.img
iov[0].iov_len = sizeof(camera_frame.img);
iov[1].iov_base = &camera_frame.meta; // iov[1] stores csi_frame.meta info
iov[1].iov_len = sizeof(camera_frame.meta);
iov[2].iov_base = camera_frame.meta.data; // iov[2] stores csi_frame.meta data
iov[2].iov_len = sizeof(camera_frame.meta) + camera_frame.meta.size;
msghdr_send.msg_iov = iov; // the io/vector info
msghdr_send.msg_iovlen = 3; // the num of iov
ssize_t size = sendmsg(socket_fd, &msghdr_send, 0);// send msg now
if (size < 0) {
LOG_E("sendmsg() failed, errno=%d, %s\n", errno, strerror(errno));
} else if (size == 0) {
LOG_W("sendmsg() failed, %zd bytes\n", size);
} else {
LOG_O("sendmsg() OK, %zd bytes\n", size);
}
// destory csi_frame
fdc_destory_csi_frame(&camera_frame);
ret = 0;
LAB_ERR_IMG_OPENED:
ret = close(img_fd);
LOG_D("close(img_fd) ret=%d, %s\n", ret, strerror(errno));
LAB_ERR_MMAPPED:
ret = munmap(dmabuf_addr, img_size);
LOG_D("munmap() ret=%d, %s\n", ret, strerror(errno));
LAB_ERR_BUF_ALLOCED:
ret = close(dmabuf_fd);
LOG_D("close(dmabuf_fd) ret=%d, %s\n", ret, strerror(errno));
LAB_ERR_ION_OPENED:
close(ion_fd);
LOG_D("close(ion_fd) ret=%d, %s\n", ret, strerror(errno));
LAB_EXIT:
ret = close(socket_fd);
LOG_D("close(socket_fd) ret=%d, %s\n", ret, strerror(errno));
if (ret)
LOG_E("Exiting producer\n");
else
LOG_D("Exiting producer\n");
return ret;
}

View File

@@ -0,0 +1,214 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#define LOG_LEVEL 2
//#define LOG_PREFIX "demo_common"
#include <syslog.h>
#include <ion.h>
#include <csi_frame.h>
#include <csi_camera_frame.h>
#include "frame_demo_common.h"
#define PAGE_SIZE 4096
//#define IMG_YUV420_FILENAME "../resource/yuv420_1280x720_csky2016.yuv"
#define IMG_RESOLUTION_WIDTH 1280
#define IMG_RESOLUTION_HEIGHT 720
/* fdc = frame demo common */
int fdc_get_img_file_size(long *img_size, const char *filename)
{
struct stat img_stat;
if (stat(filename, &img_stat) != 0) {
LOG_E("stat file '%s' failed, %s\n", filename, strerror(errno));
return -1;
}
*img_size = img_stat.st_size;
LOG_O("Get image '%s' size=%ld\n", filename, *img_size);
return 0;
}
int fdc_get_ion_device_fd(int *ion_fd)
{
*ion_fd = open(ION_DEVICE_NAME, O_RDWR);
if (*ion_fd < 0) {
LOG_E("Open ion device:'%s' failed, %s\n", ION_DEVICE_NAME, strerror(errno));
return -1;
}
LOG_O("Open ion device OK, ion_fd=%d\n", *ion_fd);
return 0;
}
int fdc_alloc_ion_buf(struct ion_allocation_data *alloc_data,
int ion_fd, unsigned long img_size)
{
alloc_data->len = img_size;
if (ioctl(ion_fd, ION_IOC_ALLOC, alloc_data) ||
alloc_data->fd < 0) {
LOG_E("ion ioctl failed, %s\n", strerror(errno));
return -1;
}
int dmabuf_fd = alloc_data->fd;
LOG_O("Alloc %ld from ion device OK, dmabuf_fd=%d\n", img_size, dmabuf_fd);
return 0;
}
int fdc_mmap_dmabuf_addr(void **addr, unsigned long length, int dmabuf_fd)
{
LOG_D("Enter, length=%zd, dmabuf_fd=%d\n", length, dmabuf_fd);
*addr = mmap(NULL, length, PROT_READ | PROT_WRITE,
MAP_SHARED, dmabuf_fd, 0);
if (*addr == NULL || *addr == MAP_FAILED) {
LOG_E("Map dmabuf failed\n");
return -1;
}
LOG_O("mmap dmabuf to user addr: %p OK\n", *addr);
return 0;
}
int fdc_store_img_to_dmabuf(void *dmabuf_addr, int img_fd, long img_size)
{
long totle_len=0, read_len = 0;
char *img_ptr = (char*)dmabuf_addr;
while ((read_len = read(img_fd, (img_ptr + totle_len), PAGE_SIZE)) > 0) {
totle_len += read_len;
}
if (read_len < 0) {
LOG_E("Read from image file failed, %s\n", strerror(errno));
return -1;
}
if (totle_len != img_size) {
LOG_E("Read total len(%ld) != stat size(%ld)\n", totle_len, img_size);
return -1;
}
LOG_O("Store image into dma-buf OK\n");
return 0;
}
int fdc_create_csi_frame(csi_frame_s *camera_frame,
csi_img_format_t *img_format, csi_camera_meta_s **camera_meta,
long img_size, int dmabuf_fd, void *dmabuf_addr)
{
// fill csi_frame's img info
camera_frame->img.type = CSI_IMG_TYPE_DMA_BUF;
camera_frame->img.size = img_size;
camera_frame->img.width = img_format->width;
camera_frame->img.height = img_format->height;
camera_frame->img.pix_format = img_format->pix_fmt;
camera_frame->img.num_planes = 1; // Now use only 1 plane data
camera_frame->img.fds[0] = dmabuf_fd;
camera_frame->img.strides[0] = img_format->width;
camera_frame->img.offsets[0] = 0;
camera_frame->img.fds[1] = -1;
camera_frame->img.strides[1] = 0;
camera_frame->img.offsets[1] = 0;
camera_frame->img.fds[2] = -1;
camera_frame->img.strides[2] = 0;
camera_frame->img.offsets[2] = 0;
camera_frame->img.modifier = 0;
// prepare csi_camera_frame meta info
int meta_unit_count = 5;
size_t meta_data_size;
csi_camera_frame_alloc_meta(camera_meta, meta_unit_count, &meta_data_size);
(*camera_meta)->units[0].id = CSI_CAMERA_META_ID_CAMERA_NAME;
(*camera_meta)->units[0].type = CSI_META_VALUE_TYPE_STR;
strncpy((*camera_meta)->units[0].str_value, "/dev/video0",
sizeof((*camera_meta)->units[0].str_value));
(*camera_meta)->units[1].id = CSI_CAMERA_META_ID_CHANNEL_ID;
(*camera_meta)->units[1].type = CSI_META_VALUE_TYPE_UINT;
(*camera_meta)->units[1].uint_value = 1;
(*camera_meta)->units[2].id = CSI_CAMERA_META_ID_FRAME_ID;
(*camera_meta)->units[2].type = CSI_META_VALUE_TYPE_INT;
(*camera_meta)->units[2].uint_value = 2;
(*camera_meta)->units[3].id = CSI_CAMERA_META_ID_TIMESTAMP;
(*camera_meta)->units[3].type = CSI_META_VALUE_TYPE_TIMEVAL;
gettimeofday(&(*camera_meta)->units[3].time_value, NULL);
(*camera_meta)->units[4].id = CSI_CAMERA_META_ID_HDR;
(*camera_meta)->units[4].type = CSI_META_VALUE_TYPE_TIMEVAL;
(*camera_meta)->units[4].bool_value = false;
camera_frame->meta.type = CSI_META_TYPE_CAMERA;
camera_frame->meta.size = meta_data_size;
camera_frame->meta.data = *camera_meta;
LOG_D("*camera_meta=camera_frame->meta.data=%p\n", camera_frame->meta.data);
return 0;
}
void fdc_dump_camera_meta(csi_camera_meta_s *camera_meta)
{
int ret;
csi_camrea_meta_unit_s meta_unit;
ret = csi_camera_frame_get_meta_unit(&meta_unit, camera_meta, CSI_CAMERA_META_ID_TIMESTAMP);
if (ret == 0) {
struct timeval tv = meta_unit.time_value;
struct tm *t = localtime(&tv.tv_sec);
if (t != NULL) {
LOG_O("Get timestamp from csi frame:%d-%d-%d %d:%d:%d.%ld\n",
1900+t->tm_year, 1+t->tm_mon, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec);
return;
} else {
LOG_E("timestamp is invalid\n");
return;
}
}
return;
}
void fdc_destory_csi_frame(csi_frame_s *camera_frame)
{
if (camera_frame->meta.data != NULL)
csi_camera_frame_free_meta((csi_camera_meta_s*)camera_frame->meta.data);
}
void fdc_dump_msghdr(struct msghdr *msg)
{
int i;
if (msg == NULL) {
LOG_E("mgs = NULL\n");
return;
}
LOG_D("struct msghdr *msg(%p) = {\n", msg);
LOG_D("\t .msg_iov=%p\n", msg->msg_iov);
LOG_D("\t .msg_iovlen=%zd\n", msg->msg_iovlen);
for(i = 0; i < msg->msg_iovlen; i++) {
struct iovec *iovc = &(msg->msg_iov[i]);
LOG_D("\t .msg_iov[%d]={.iov_base=%p, .iov_len=%zd}\n",
i, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
}
LOG_D("\t .msg_control=%p\n", msg->msg_control);
LOG_D("\t .msg_control=%zd\n", msg->msg_controllen);
LOG_D("\t .name=%p\n", msg->msg_name);
LOG_D("\t .msg_namelen=%d\n", msg->msg_namelen);
LOG_D("\t .msg_flags=%d\n", msg->msg_flags);
LOG_D("}\n");
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __FRAME_DEMO_COMMON_H__
#define __FRAME_DEMO_COMMON_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <ion.h>
#include <csi_frame.h>
#include <csi_camera_frame.h>
#define ION_DEVICE_NAME "/dev/ion"
extern const int PAGE_SIZE;
extern const char *IMG_YUV420_FILENAME;
extern const int IMG_RESOLUTION_WIDTH;
extern const int IMG_RESOLUTION_HEIGHT;;
int fdc_get_img_file_size(long *img_size, const char *filename);
int fdc_get_ion_device_fd(int *ion_fd);
int fdc_alloc_ion_buf(struct ion_allocation_data *alloc_data,
int ion_fd, unsigned long img_size);
int fdc_mmap_dmabuf_addr(void **addr, unsigned long length, int dmabuf_fd);
int fdc_store_img_to_dmabuf(void *dmabuf_addr, int img_fd, long img_size);
int fdc_create_csi_frame(csi_frame_s *camera_frame,
csi_img_format_t *img_format, csi_camera_meta_s **camera_meta,
long img_size, int dmabuf_fd, void *dmabuf_addr);
void fdc_dump_camera_meta(csi_camera_meta_s *camera_meta);
void fdc_destory_csi_frame(csi_frame_s *camera_frame);
void fdc_dump_msghdr(struct msghdr *msg);
#endif /* __FRAME_DEMO_COMMON_H__ */

1070
examples/g2d/g2d_demo.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

3
examples/vdec/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
vdec_demo1
vdec_demo2
vdec_demo3

30
examples/vdec/Makefile Normal file
View File

@@ -0,0 +1,30 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
DIR_TO_ROOT=../..
include $(DIR_TO_ROOT)/build.param
#CFLAGS +=
LIBS += -lhal_common -lhal_platform
OUTPUT_DIR := $(DIR_TO_ROOT)/output/examples/vdec
#PREPARE := lib_camera
TARGET_1 := vdec_demo1
SRCS_1 = vdec_demo1.c
TARGET_ALL := $(TARGET_1)
all: $(TARGET_ALL)
clean:
rm -rf .obj
rm -f $(TARGET_1) $(OUTPUT_DIR)/$(TARGET_1)
include $(DIR_TO_ROOT)/common_target.mk
.PHONY: clean all

172
examples/vdec/vdec_demo1.c Normal file
View File

@@ -0,0 +1,172 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "vdec_demo1"
#include <syslog.h>
#include <csi_vdec.h>
#include <csi_allocator.h>
#define TEST_MODULE_NAME "simulator_vdec0"
int main(int argc, char *argv[])
{
int ret;
csi_vdec_info_t vdec_info;
csi_vdec_dev_t decoder;
csi_vdec_chn_t channel;
// 打印HAL接口版本号
csi_api_version_u version;
csi_vdec_get_version(&version);
printf("Video Decoder HAL version: %d.%d\n", version.major, version.minor);
// 获取设备中所有的Video Decoder
struct csi_vdec_infos vdec_infos;
csi_vdec_query_list(&vdec_infos);
// 打印所有设备所支持的Video Decoder
bool found_module = false;
for (int i = 0; i < vdec_infos.count; i++) {
csi_vdec_info_t *info;
info = &(vdec_infos.info[i]);
printf("decoder[%d]: module_name='%s', device_name='%s', capabilities=0x%lx\n",
i, info->module_name, info->device_name, info->capabilities);
if (strcmp(info->module_name, TEST_MODULE_NAME) == 0) {
vdec_info = *info;
found_module = true;
}
}
if (!found_module) {
LOG_E("Can't find module_name:'%s'\n", TEST_MODULE_NAME);
exit(-1);
}
// 打开设备获取句柄,作为后续操对象
csi_vdec_open(&decoder, vdec_info.device_name);
// 创建视频解码通道
csi_vdec_config_s dec_cfg;
dec_cfg.input_mode = CSI_VDEC_INPUT_MODE_FRAME;
dec_cfg.input_stream_buf_size = 1*1024*1024;
dec_cfg.output_format = CSI_PIX_FMT_I420;
dec_cfg.output_width = 1920;
dec_cfg.output_height = 1080;
dec_cfg.output_order = CSI_VDEC_OUTPUT_ORDER_DISP;
dec_cfg.dec_vcodec_id = CSI_VCODEC_ID_H264;
dec_cfg.output_img_type = CSI_VDEC_MODE_IPB;
dec_cfg.dec_frame_buf_cnt = 8;
csi_vdec_create_channel(&channel, decoder, &dec_cfg);
// 配置内存分配器
if (1) {
//csi_allocator_s *allocator = csi_allocator_get(CSI_ALLOCATOR_TYPE_DMA);
//csi_vdec_set_memory_allocator(channel, allocator);
} else {
csi_frame_s *allocated_frames[8]; // TODO: allocate frames first
csi_vdec_register_frames(channel, allocated_frames, 8);
}
// 配置解码通道模式
csi_vdec_mode_s vdec_mode;
vdec_mode.fb_source = CSI_FB_SOURCE_DMABUF;
vdec_mode.low_latency_mode = false;
vdec_mode.mini_buf_mode = false;
csi_vdec_set_mode(channel, &vdec_mode);
// 获取和重新配置解码通道属性
csi_vdec_get_chn_config(channel, &dec_cfg);
dec_cfg.dec_frame_buf_cnt = 16;
csi_vdec_set_chn_config(channel, &dec_cfg);
// 订阅事件
csi_vdec_event_handle_t event_handle;
csi_vdec_create_event_handle(&event_handle, decoder);
csi_vdec_event_subscription_t subscribe_dec, subscribe_chn;
subscribe_dec.type = CSI_VDEC_EVENT_TYPE_DECODER; // 订阅Decoder事件
subscribe_dec.id = CSI_VDEC_EVENT_ID_ERROR;
csi_vdec_subscribe_event(event_handle, &subscribe_dec);
subscribe_chn.type = CSI_VDEC_EVENT_TYPE_CHANNEL; // 订阅Channel事件
subscribe_chn.id = CSI_VDEC_CHANNEL_EVENT_ID_FRAME_READY;
csi_vdec_subscribe_event(event_handle, &subscribe_chn);
// 传送视频码流
csi_vdec_start(channel);
const int send_count = 25;
const int stream_packet_len = 1024;
csi_vdec_stream_s stream;
stream.data = malloc(stream_packet_len);
for (int i = 0; i < send_count; i++) {
stream.length = stream_packet_len;
stream.pts = 40 * i;
stream.eos = (i < (send_count - 1)) ? false : true;
if (i == 10) {
// Just for testing
csi_vdec_reset(channel);
}
csi_vdec_send_stream_buf(channel, &stream, 1000);
}
free(stream.data);
stream.data = NULL;
// 收取解码结果
csi_frame_s *frame;
struct csi_vdec_event event;
int get_count = 0;
csi_vdec_chn_status_s status;
while (get_count < send_count) {
// timeout unit: ms, -1 means wait forever, or until error occurs
csi_vdec_get_event(event_handle, &event, -1);
switch (event.type) {
case CSI_VDEC_EVENT_TYPE_DECODER:
csi_vdec_query_status(channel, &status);
// Dump Status
break;
case CSI_VDEC_EVENT_TYPE_CHANNEL:
switch (event.id) {
case CSI_VDEC_CHANNEL_EVENT_ID_FRAME_READY:
csi_vdec_get_frame(channel, &frame, 1000);
get_count++;
// display frame
// release frame: frame.release();
}
break;
default:
break;
}
}
// 关闭与回收资源
csi_vdec_stop(channel);
csi_vdec_unsubscribe_event(event_handle, &subscribe_dec);
csi_vdec_unsubscribe_event(event_handle, &subscribe_chn);
csi_vdec_destory_channel(channel);
csi_vdec_close(decoder);
return 0;
}

1
examples/venc/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
venc_demo1

30
examples/venc/Makefile Normal file
View File

@@ -0,0 +1,30 @@
##
# Copyright (C) 2021 Alibaba Group Holding Limited
# Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
##
DIR_TO_ROOT=../..
include $(DIR_TO_ROOT)/build.param
#CFLAGS +=
LIBS += -lhal_common -lhal_platform
OUTPUT_DIR := $(DIR_TO_ROOT)/output/examples/venc
#PREPARE := lib_camera
TARGET_1 := venc_demo1
SRCS_1 = venc_demo1.c
TARGET_ALL := $(TARGET_1)
all: $(TARGET_ALL)
clean:
rm -rf .obj
rm -f $(TARGET_1) $(OUTPUT_DIR)/$(TARGET_1)
include $(DIR_TO_ROOT)/common_target.mk
.PHONY: clean all

179
examples/venc/venc_demo1.c Normal file
View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LOG_LEVEL 3
#define LOG_PREFIX "venc_demo1"
#include <syslog.h>
#include <csi_venc.h>
#define TEST_MODULE_NAME "simulator_venc0"
int main(int argc, char *argv[])
{
int ret;
csi_venc_info_s venc_info;
csi_venc_dev_t encoder;
csi_venc_chn_t channel;
// 打印HAL接口版本号
csi_api_version_u version;
csi_venc_get_version(&version);
printf("Video Encoder HAL version: %d.%d\n", version.major, version.minor);
// 获取设备中所有的Video Encoder
struct csi_venc_infos venc_infos;
csi_venc_query_list(&venc_infos);
// 打印所有设备所支持的Video Encoder
bool found_module = false;
for (int i = 0; i < venc_infos.count; i++) {
csi_venc_info_s *info;
info = &(venc_infos.info[i]);
printf("decoder[%d]: module_name='%s', device_name='%s', capabilities=0x%lx\n",
i, info->module_name, info->device_name, info->capabilities);
if (strcmp(info->module_name, TEST_MODULE_NAME) == 0) {
venc_info = *info;
found_module = true;
}
}
if (!found_module) {
LOG_E("Can't find module_name:'%s'\n", TEST_MODULE_NAME);
exit(-1);
}
// 打开设备获取句柄,作为后续操对象
csi_venc_open(&encoder, venc_info.device_name);
// 创建视频解码通道
csi_venc_chn_cfg_s chn_cfg;
chn_cfg.attr.enc_vcodec_id = CSI_VCODEC_ID_H264;
chn_cfg.attr.max_pic_width = 3840;
chn_cfg.attr.max_pic_height = 2160;
chn_cfg.attr.input_format = CSI_PIX_FMT_I420;
chn_cfg.attr.pic_width = 1920;
chn_cfg.attr.pic_height = 1080;
chn_cfg.attr.buf_size = 1*1024*1024;
chn_cfg.attr.h264_attr.profile = CSI_VENC_H264_PROFILE_HIGH;
chn_cfg.attr.h264_attr.level = CSI_VENC_H264_LEVEL_4;
chn_cfg.attr.h264_attr.frame_type = CSI_VCODEC_I_FRAME |
CSI_VCODEC_P_FRAME |
CSI_VCODEC_B_FRAME;
chn_cfg.attr.h264_attr.share_buf = true;
chn_cfg.gop.gop_num = 5;
chn_cfg.gop.gop_mode = CSI_VENC_GOPMODE_NORMALP;
chn_cfg.gop.normalp.ip_qp_delta = 10;
chn_cfg.rc.rc_mode = CSI_VENC_RC_MODE_H264CBR;
chn_cfg.rc.h264_vbr.stat_time = 10;
chn_cfg.rc.h264_vbr.framerate_numer = 25;
chn_cfg.rc.h264_vbr.framerate_denom = 1;
chn_cfg.rc.h264_vbr.max_bit_rate = 16 * 1024; // kbps
csi_venc_create_channel(&channel, encoder, &chn_cfg);
// 配置内存分配器
//csi_allocator_s *allocator = csi_allocator_get(CSI_ALLOCATOR_TYPE_DMA);
//csi_venc_set_memory_allocator(channel, allocator);
// 设置解码通道扩展属性
csi_venc_chn_ext_property_s ext_property;
ext_property.prop_id = CSI_VENC_EXT_PROPERTY_ROI;
ext_property.roi_prop.index = 0;
ext_property.roi_prop.enable = true;
ext_property.roi_prop.abs_qp = 1;
ext_property.roi_prop.qp = 51;
csi_venc_set_ext_property(channel, &ext_property);
// 订阅事件
csi_venc_event_handle_t event_handle;
csi_venc_create_event_handle(&event_handle, encoder);
csi_venc_event_subscription_s subscribe_dec, subscribe_chn;
subscribe_dec.type = CSI_VENC_EVENT_TYPE_DECODER; // 订阅Encoder事件
subscribe_dec.id = CSI_VENC_EVENT_ID_ERROR;
csi_venc_subscribe_event(event_handle, &subscribe_dec);
subscribe_chn.type = CSI_VENC_EVENT_TYPE_CHANNEL; // 订阅Channel事件
subscribe_chn.id = CSI_VENC_CHANNEL_EVENT_ID_FRAME_READY;
csi_venc_subscribe_event(event_handle, &subscribe_chn);
// 传送视频码流
csi_venc_start(channel);
csi_frame_s frame;
int send_count = 25;
for (int i = 0; i < send_count; i++) {
if (i == 10) {
// Just for testing
csi_venc_reset(channel);
}
if (i %5 != 0) {
// Send normal frame
csi_venc_send_frame(channel, &frame, 1000);
}
else {
// Send frame with extended properties
csi_venc_frame_prop_s frame_prop[2];
frame_prop[0].type = CSI_VENC_FRAME_PROP_FORCE_IDR;
frame_prop[0].force_idr = true;
frame_prop[1].type = CSI_VENC_FRAME_PROP_FORCE_SKIP;
frame_prop[1].force_skip = false;
csi_venc_send_frame_ex(channel, &frame, 1000,
frame_prop, ARRAY_SIZE(frame_prop));
}
}
// 收取解码结果
csi_stream_s stream;
struct csi_venc_event event;
int get_count = 0;
csi_venc_chn_status_s status;
while (get_count < send_count) {
int timeout = -1; // unit: ms, -1 means wait forever, or until error occurs
csi_venc_get_event(event_handle, &event, timeout);
switch (event.type) {
case CSI_VENC_EVENT_TYPE_DECODER:
csi_venc_query_status(channel, &status);
// Dump Status
break;
case CSI_VENC_EVENT_TYPE_CHANNEL:
switch (event.id) {
case CSI_VENC_CHANNEL_EVENT_ID_FRAME_READY:
csi_venc_get_stream(channel, &stream, 1000);
// save stream ...
// release stream: stream.release();
}
break;
default:
break;
}
}
// 关闭与回收资源
csi_venc_stop(channel);
csi_venc_unsubscribe_event(event_handle, &subscribe_dec);
csi_venc_unsubscribe_event(event_handle, &subscribe_chn);
csi_venc_destory_channel(channel);
csi_venc_close(encoder);
return 0;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CAMERA_STRING_H__
#define __CAMERA_STRING_H__
#include <stdio.h>
#include <string.h>
#include <csi_camera.h>
#include <camera_manager.h>
#ifdef __cplusplus
extern "C" {
#endif
const char *camera_string_enum_name(int property_id, int enum_id);
const char *camera_string_bitmask_name(int property_id, int enum_id);
const char *camera_string_capture_type(csi_camera_channel_capture_type_e type, bool accept_unknown);
const char *camera_string_chn_capture_types(int fields, char *fields_string);
const char *camera_string_pixel_format(csi_pixel_fmt_e pix_fmt);
const char *camera_string_img_type(csi_img_type_e img_type);
const char *camera_string_meta_field(csi_camera_meta_id_e type, bool accept_unknown);
const char *camera_string_chn_meta_fields(int fields, char *fields_string);
const char *camera_string_chn_status(csi_img_type_e img_type);
const char *camera_string_camera_event_type(csi_camera_event_id_e event_id);
const char *camera_string_channel_event_type(csi_camera_channel_event_id_e event_id);
const char *camera_string_channel_action(camera_channel_action_e action);
const char *camera_string_camera_action(camera_action_e action);
#ifdef __cplusplus
}
#endif
#endif /* __CAMERA_STRING_H__ */

65
include/common/common.h Normal file
View File

@@ -0,0 +1,65 @@
/*
* Copyright 2018 C-SKY Microsystems Co., Ltd.
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __COMMON_H__
#define __COMMON_H__
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include <mcheck.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "common_errno.h"
#include "common_datatype.h"
#include "syslog.h"
#include "list.h"
#define CHECK_RET_RETURN(ret) \
if (ret != 0) { \
LOG_E("failed, ret=%d\n", ret); \
return ret; \
}
#define CHECK_RET_EXIT(ret) \
if (ret != 0) { \
LOG_E("failed, ret=%d\n", ret); \
exit(ret); \
}
#define CHECK_RET_WARNING(ret) \
if (ret != 0) { \
LOG_W("Warning, ret=%d\n", ret); \
}
#define CHECK_POINTER_RETURN(pointer) \
if (pointer == NULL) { \
LOG_E("pointer is NULL\n"); \
return ERRNO_INVALID_PARAMETER; \
}
#endif /* __COMMON_H__ */

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2018 C-SKY Microsystems Co., Ltd.
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __COMMON_DATATYPE_H__
#define __COMMON_DATATYPE_H__
#ifndef NULL
#define NULL 0x00
#endif
#ifndef TRUE
#define TRUE 0x01
#endif
#ifndef FALSE
#define FALSE 0x00
#endif
#ifndef true
#define true 0x01
#endif
#ifndef false
#define false 0x00
#endif
#ifndef bool
typedef unsigned char bool;
#endif
#if 0 /* below types are defined in /usr/include/stdint.h */
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned long long uint64_t;
#endif
#endif /* __COMMON_DATATYPE_H__ */

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2018 C-SKY Microsystems Co., Ltd.
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __COMMON_ERRNO_H__
#define __COMMON_ERRNO_H__
#include <errno.h>
typedef enum {
FAILURE = -1,
SUCCESS = 0,
ERRNO_INVALID_PARAMETER,
ERRNO_INVALID_STATE,
ERRNO_INVALID_CLIENT_PACKAGE,
} common_errno_e;
#endif /* __COMMON_ERRNO_H__ */

View File

@@ -0,0 +1,20 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __DUMP_UTILS_H__
#define __DUMP_UTILS_H__
#include <stdio.h>
#include <string.h>
#include <csi_frame.h>
void csi_dump_hex(char *data, int length, char *name);
void csi_dump_img_info(csi_img_s *img);
#endif // __DUMP_UTILS_H__

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
union {
struct cmsghdr cm; // control msg
char ctl[CMSG_SPACE(sizeof(int))]; // the pointer of char
} ctl_un;

154
include/common/list.h Normal file
View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) HighPoint Technologies, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/dev/hptrr/list.h,v 1.2.2.1.4.1 2010/06/14 02:09:06 kensmith Exp $
*/
/*
* $Id: list.h,v 1.6 2006/10/31 06:25:28 gmm Exp $
* Copyright (C) 2004-2005 HighPoint Technologies, Inc. All rights reserved.
*/
#ifndef _HPT_LIST_H_
#define _HPT_LIST_H_
#ifndef _LINUX_LIST_H
#ifndef _LINUX_TYPES_H
#ifndef HPT_INLINE
#define HPT_INLINE __inline
#endif
typedef unsigned long HPT_UPTR;
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define INIT_LIST_HEAD(ptr) do { (ptr)->next = (ptr); (ptr)->prev = (ptr); } while (0)
static HPT_INLINE void __list_add(struct list_head * _new, struct list_head * prev, struct list_head * next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}
static HPT_INLINE void list_add(struct list_head *_new, struct list_head *head)
{
__list_add(_new, head, head->next);
}
static HPT_INLINE void list_add_tail(struct list_head *_new, struct list_head *head)
{
__list_add(_new, head->prev, head);
}
static HPT_INLINE void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
static HPT_INLINE void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
static HPT_INLINE void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
static HPT_INLINE int list_empty(struct list_head *head)
{
return head->next == head;
}
static HPT_INLINE void __list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
static HPT_INLINE void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}
static HPT_INLINE void list_splice_init(struct list_head *list, struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
/*#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(HPT_UPTR)(&((type *)0)->member))) */
#define list_entry(ptr, type, member) \
((type *)((unsigned long)(ptr)-((unsigned long)(&((type *)1)->member) - 1)))
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#define get_first_item(attached, type, member) \
((type *)((char *)((attached)->next)-(HPT_UPTR)(&((type *)0)->member)))
#endif
#endif
#endif

50
include/common/llist.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: zhuxinran <fuqian.zxr@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LLIST_H__
#define __LLIST_H__
#ifdef __cplusplus
extern "C" {
#endif
#define LLIST_FORWARD 1
#define LLIST_BACKWARD 2
typedef void llist_op(const void *);
typedef int llist_cmp(const void *, const void *);
struct llist_node_st {
struct llist_node_st *prev;
struct llist_node_st *next;
char data[1];
};
typedef struct llist_head_st {
int size;
struct llist_node_st head;
int (*insert)(struct llist_head_st *, const void *data, int mode);
void *(*find)(struct llist_head_st *, const void *data, llist_cmp *cmp);
int (*delete)(struct llist_head_st *, const void *data, llist_cmp *cmp);
int (*fetch)(struct llist_head_st *, const void *data, llist_cmp *cmp,
void *rdata);
void (*travel)(struct llist_head_st *, llist_op *op);
} LLIST;
LLIST *llist_create(int size);
void llist_destroy(LLIST *);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2018-2019 C-SKY Microsystems Co., Ltd.
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __PRODUCER_CONSUMER_ASYNC_H__
#define __PRODUCER_CONSUMER_ASYNC_H__
#include "common.h"
struct pca_data_info;
typedef int32_t (*pca_consumed_callback)(struct pca_data_info* data_info);
typedef struct pca_data_info {
void* data; /* data pointer */
uint32_t length; /* data length */
uint32_t type; /* data type */
pca_consumed_callback consumed_callback;/* data need free by dispatcher */
} pca_data_info_t;
typedef struct pca_data_statistics {
uint32_t total_delivered; /* Data feeded in */
uint32_t total_discarded; /* Data discarded because busy */
uint32_t total_updated; /* New data updated in before consume */
uint32_t total_consumed; /* Data consumed */
} pca_data_statistics_t;
typedef int32_t (*pca_consumer_process)(pca_data_info_t* data_info);
typedef struct pca_thread_info {
pthread_t tid; /* thread ID */
char name[32]; /* thread name */
sem_t sem_wakeup; /* semphore to wakeup thread */
bool is_running;
pca_data_info_t data_info; /* the data delivered from parent */
bool has_new_data; /* indicate there is new data to handle */
bool need_unlock_data_mutex; /* Just for mark flag when need unlock */
pthread_mutex_t mutex_data; /* mutex to protect handling data */
pca_data_statistics_t stats; /* the statistics of data */
} pca_thread_info_t;
typedef struct pca_consumer_processor_info {
pca_consumer_process process; /* consumer processor function */
int data_type; /* the data type to be consume */
char name[16]; /* consumer name for debug */
} pca_consumer_processor_info_t;
struct pca_dispatcher_info; /* Declare here but defined below */
typedef struct pca_consumer_list_info {
pca_thread_info_t thread_info; /* thread info */
pca_consumer_processor_info_t processor;/* post processor info */
struct list_head list; /* to build list */
struct pca_dispatcher_info* dispatcher; /* dispatcher's pointer */
} pca_consumer_list_info_t;
typedef struct {
pca_data_info_t data_info; /* data_info */
unsigned int reference_count; /* data using count */
struct list_head list; /* to build list */
} pca_data_free_list_info_t;
typedef struct pca_dispatcher_info {
pca_thread_info_t thread_info; /* thread info */
pthread_mutex_t consumer_mutex; /* mutex to protect consumer_list */
pca_consumer_list_info_t consumer_list; /* consumers list */
pthread_mutex_t data_free_mutex; /* mutex to protect data_free_list */
pca_data_free_list_info_t data_free_list;/* data list need to free */
} pca_dispatcher_info_t;
int32_t pca_dispatcher_create(pca_dispatcher_info_t** dispatcher, char* name);
int32_t pca_dispatcher_run(pca_dispatcher_info_t* dispatcher);
int32_t pca_dispatcher_feed(pca_dispatcher_info_t* dispatcher,
void *data, int32_t data_type);
int32_t pca_dispatcher_stop(pca_dispatcher_info_t* dispatcher);
int32_t pca_dispatcher_destory(pca_dispatcher_info_t* dispatcher);
int32_t pca_add_consumer_processor(pca_dispatcher_info_t* dispatcher,
pca_consumer_processor_info_t *processor);
int32_t pca_remove_consumer_processor(pca_dispatcher_info_t* dispatcher,
pca_consumer_processor_info_t *processor);
int32_t pca_feed_consumers(pca_dispatcher_info_t* dispatcher,
pca_data_info_t* data_info);
int32_t pca_feed_dispatcher(pca_dispatcher_info_t* dispatcher,
pca_data_info_t* data_info);
#endif /* __PRODUCER_CONSUMER_ASYNC_H__ */

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: zhuxinran <fuqian.zxr@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* Copyright (C) 2017-2020 Alibaba Group Holding Limited
*/
#ifndef _DRV_RINGBUFFER_H_
#define _DRV_RINGBUFFER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
#include <stdbool.h>
typedef struct ringbuffer {
uint8_t *buffer;
uint32_t size;
uint32_t write;
uint32_t read;
uint32_t data_len;
} ringbuffer_t;
void ringbuffer_reset(ringbuffer_t *fifo);
uint32_t ringbuffer_len(ringbuffer_t *fifo);
uint32_t ringbuffer_avail(ringbuffer_t *fifo);
bool ringbuffer_is_empty(ringbuffer_t *fifo);
bool ringbuffer_is_full(ringbuffer_t *fifo);
/*write to ringbuffer*/
uint32_t ringbuffer_in(ringbuffer_t *fifo, const void *in, uint32_t len);
/*read to ringbuffer*/
uint32_t ringbuffer_out(ringbuffer_t *fifo, void *out, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif /* _DRV_RINGBUFFER_H_ */

111
include/common/syslog.h Normal file
View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#ifndef SYSLOG_H
#define SYSLOG_H
#define LOG_ENABLE
#ifdef LOG_LEVEL
#if (LOG_LEVEL >= 3)
#define LOG_ENABLE_D
#endif
#if (LOG_LEVEL >= 2)
#define LOG_ENABLE_I
#endif
#if (LOG_LEVEL >= 1)
#define LOG_ENABLE_W
#endif
#if (LOG_LEVEL >= 0)
#define LOG_ENABLE_E
#endif
#else /* #ifdef LOG_LEVEL */
#define LOG_ENABLE_E /* Default level if LOG_LEVEL not defiend */
#endif /* #ifdef LOG_LEVEL */
/* [LogLevel:FileName:Function:Line] */
extern const char *PFORMAT_D;
extern const char *PFORMAT_I;
extern const char *PFORMAT_W;
extern const char *PFORMAT_E;
extern const char *PFORMAT_O;
#ifdef LOG_PREFIX
#define LOG_PREF LOG_PREFIX"-"
#else
#define LOG_PREF ""
#endif
#define LOG_E_BASE_ARGS LOG_PREF, __FUNCTION__, __LINE__
#define LOG_W_BASE_ARGS LOG_PREF, __FUNCTION__, __LINE__
#define LOG_I_BASE_ARGS LOG_PREF, __FUNCTION__, __LINE__
#define LOG_D_BASE_ARGS LOG_PREF, __FUNCTION__, __LINE__
#define LOG_O_BASE_ARGS LOG_PREF, __FUNCTION__, __LINE__
/* Log in freely format without prefix */
#ifdef LOG_ENABLE
#define LOG_F(fmt, args...) printf(fmt,##args)
#else
#define LOG_F(fmt, args...)
#endif
// OK, Green color
#define LOG_O(fmt, args...) \
do {printf(PFORMAT_O,LOG_O_BASE_ARGS); printf(fmt,##args);} while(0)
#define LOGPRINT_E printf
#define LOGPRINT_W printf
#define LOGPRINT_I printf
#define LOGPRINT_D printf
/* Log debug */
#if defined(LOG_ENABLE_D) && defined(LOG_ENABLE)
#define LOG_D(fmt, args...) \
do {LOGPRINT_D(PFORMAT_D,LOG_D_BASE_ARGS); LOGPRINT_D(fmt,##args);} while(0)
#else
#define LOG_D(fmt, args...)
#endif
/* Log information */
#if defined(LOG_ENABLE_I) && defined(LOG_ENABLE)
#define LOG_I(fmt, args...) \
do {LOGPRINT_I(PFORMAT_I ,LOG_I_BASE_ARGS); LOGPRINT_I(fmt,##args);} while(0)
#else
#define LOG_I(fmt, args...)
#endif
/* Log warning */
#if defined(LOG_ENABLE_W) && defined(LOG_ENABLE)
#define LOG_W(fmt, args...) \
do {LOGPRINT_W(PFORMAT_W,LOG_W_BASE_ARGS); LOGPRINT_W(fmt,##args);} while(0)
#else
#define LOG_W(fmt, args...)
#endif
/* Log error */
#if defined(LOG_ENABLE_E) && defined(LOG_ENABLE)
#define LOG_E(fmt, args...) \
do{LOGPRINT_E(PFORMAT_E,LOG_E_BASE_ARGS); LOGPRINT_E(fmt,##args);} while(0)
#else
#define LOG_E(fmt, args...)
#endif
#define ENTER_VOID() LOG_D("Enter\n")
#define EXIT_VOID() do { LOG_D("Exit\n"); return;} while(0)
#define EXIT_INT(val) do { LOG_D("Exit, return val=%d\n", (int)val); return val;} while(0)
#define EXIT_PTR(ptr) do { LOG_D("Exit, return ptr=%p\n", (void*)ptr); return ptr;} while(0)
#endif // SYSLOG_H

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_ALLOCATOR_H__
#define __CSI_ALLOCATOR_H__
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
typedef enum csi_allocator_type {
CSI_ALLOCATOR_TYPE_SYSTEM,
CSI_ALLOCATOR_TYPE_SYSTEM_CONTIG,
CSI_ALLOCATOR_TYPE_CARVEOUT,
CSI_ALLOCATOR_TYPE_DMA,
CSI_ALLOCATOR_TYPE_CUSTOM,
} csi_allocator_type_e; // refer from ion_heap_type
typedef struct csi_mem {
void *usr_addr;
union {
int64_t phy_addr; /* 0 means invalid */
int fd; /* -1 means invalid */
};
size_t size;
void *opaque; /* not for user, DO NOT use or modify it */
} csi_mem_s;
typedef struct csi_allocator {
//int (*init)(char *args);
csi_mem_s *(*alloc)(csi_allocator_type_e type, size_t size, uint32_t align);
void (*free)(csi_mem_s *mem);
void *(*map)(csi_mem_s *mem);
void (*unmap)(csi_mem_s *mem);
} csi_allocator_s;
//csi_allocator_s *csi_allocator_get(csi_allocator_type_e type);
int32_t csi_hal_set_allocator(csi_allocator_s allocator);
int32_t csi_hal_get_allocator(csi_allocator_s *allocator);
#endif /* __CSI_ALLOCATOR_H__ */

135
include/hal/csi_audio_ai.h Normal file
View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: fuqian.zxr <fuqian.zxr@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_AUDIO_AI_H__
#define __CSI_AUDIO_AI_H__
#include "csi_audio_common.h"
#define CSI_AUDIO_AI_VERSION_MAJOR 0
#define CSI_AUDIO_AI_VERSION_MINOR 1
#define VQE_DRC_SECNUM 5
#define CSI_AI_MAX_COUNT 16
#define CSI_AI_NAME_MAX_LEN 32
#define CSI_AI_CAP_SPDIF 0x00000001 /*Is a spdif device*/
#define CSI_AI_CAP_HDMI 0x00000002 /*IS a hdmi audio*/
#define CSI_AI_CAP_CODEC 0x00000003 /*Is a codec audio*/
typedef struct csi_ai_info {
char ai_name[CSI_AI_NAME_MAX_LEN];
unsigned int capbilities;
}csi_ai_info_s;
typedef struct csi_ai_infos {
unsigned int count;
csi_ai_info_s info[CSI_AI_MAX_COUNT];
}csi_ai_infos_s;
typedef struct csi_aec_frame {
csi_audio_frame_s refframe;
bool bvalid;
bool bsysbind;
}csi_aec_frame_s;
typedef struct csi_aichn_frame{
uint32_t usr_frm_depth;
}csi_aichn_frame_s;
typedef struct csi_ai_aec_config {
bool usrmode;
int8_t cngmode;
int8_t nearallpassenergy;
int8_t nearcleansupenergy;
int16_t dthnl_sort_qth;
int16_t echobandlow;
int16_t echobandhigh;
int16_t echobandlow2;
int16_t echobandhigh2;
int16_t erl_band[6];
int16_t erl[7];
int16_t voice_protect_freql;
int16_t voice_protect_freql1;
int32_t reserved;
}csi_ai_aec_config_s;
typedef struct csi_ai_rnr_config {
bool usrmode;
int32_t nrmode;
int32_t maxnrlevel;
int32_t noisethresh;
}csi_ai_rnr_config_s;
typedef struct csi_ai_hdr_config {
bool usrmode;
int32_t mingaindb;
int32_t maxgaindb;
int32_t micgaindb;
int32_t micgainstepdb;
void *callback;
}csi_ai_hdr_config_s;
typedef struct csi_ai_drc_config {
bool usrmode;
int16_t attacktime;
int16_t releasetime;
int16_t oldlevdb[VQE_DRC_SECNUM];
int16_t newlevdb[VQE_DRC_SECNUM];
}csi_ai_drc_config_s;
int32_t csi_ai_get_version(csi_api_version_u *version);
int32_t csi_ai_query_list(csi_ai_infos_s *infos);
int32_t csi_ai_setpubattr(int32_t aidevid,csi_aio_attr_s *aiattr);
int32_t csi_ai_getpubattr(int32_t aidevid,csi_aio_attr_s *aiattr);
int32_t csi_ai_enable(int32_t aidevid);
int32_t csi_ai_disable(int32_t aidevid);
int32_t csi_ai_enablechn(int32_t aidevid,int32_t aichn);
int32_t csi_ai_disablechn(int32_t aidevid,int32_t aichn);
int32_t csi_ai_getframe(int32_t aidev,int32_t aichn,csi_audio_frame_s *frm,csi_aec_frame_s *aecfrm,int32_t timeout);
int32_t csi_ai_releaseframe(int32_t aidev,int32_t aichn,csi_audio_frame_s *frm,csi_aec_frame_s *aecfrm);
int32_t csi_ai_setchnparam(int32_t aidev,int32_t aichn,csi_aichn_frame_s *chnparam);
int32_t csi_ai_getchnparam(int32_t aidev,int32_t aichn,csi_aichn_frame_s *chnparam);
int32_t csi_ai_enableresmp(int32_t aidev,int32_t aichn,csi_audio_sample_rate_e out_sample_rate);
int32_t csi_ai_disableresmp(int32_t aidev,int32_t aichn);
int32_t csi_ai_setvqeattr(int32_t aidev,int32_t aichn,int32_t aochn,int *level);
int32_t csi_ai_getvqeattr(int32_t aidev,int32_t aichn,int *level);
int32_t csi_ai_settalkvqeattr(int32_t aidev,int32_t aichn,int32_t aodev,int32_t aochn,int *level);
int32_t csi_ai_gettalkvqeattr(int32_t aidev,int32_t aichn,int *level);
int32_t csi_ai_setrecordvqeattr(int32_t aidev,int32_t aichn,int *level);
int32_t csi_ai_getrecordvqeattr(int32_t aidev,int32_t aichn,int *level);
int32_t csi_ai_enablevqe(int32_t aidev,int32_t aichn);
int32_t csi_ai_disablevqe(int32_t aidev,int32_t aichn);
int32_t csi_ai_settrackmode(int32_t aidev,csi_audio_track_mode_e trackmode);
int32_t csi_ai_gettrackmode(int32_t aidev,csi_audio_track_mode_e *trackmode);
int32_t csi_ai_reset(int32_t aidevid);
int32_t csi_ai_queryfilestatus(int32_t aidev,int32_t aichn,csi_audio_file_status_s *filestatus);
int32_t csi_ai_setvqevolume(int32_t aidev,int32_t aichn,int32_t volumedb);
int32_t csi_ai_getvqevolume(int32_t aidev,int32_t aichn,int32_t *volumedb);
int32_t csi_ai_enableaecrefframe(int32_t aidev,int32_t aichn,int32_t aodev,int32_t aochn);
int32_t csi_ai_disableaecrefframe(int32_t aidev,int32_t aichn);
#endif

113
include/hal/csi_audio_ao.h Normal file
View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: fuqian.zxr <fuqian.zxr@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_AUDIO_AO_H__
#define __CSI_AUDIO_AO_H__
#include "csi_audio_common.h"
#define CSI_AO_MAX_COUNT 16
#define CSI_AO_NAME_MAX_LEN 32
#define CSI_AO_CAP_SPDIF 0x00000001 /*Is a spdif device*/
#define CSI_AO_CAP_HDMI 0x00000002 /*IS a hdmi audio*/
#define CSI_AO_CAP_CODEC 0x00000003 /*Is a codec audio*/
typedef struct csi_ao_info {
char ai_name[CSI_AO_NAME_MAX_LEN];
unsigned int capbilities;
}csi_ao_info_s;
typedef struct csi_ao_infos {
unsigned int count;
csi_ao_info_s info[CSI_AO_MAX_COUNT];
}csi_ao_infos_s;
#define CSI_AUDIO_AO_VERSION_MAJOR 0
#define CSI_AUDIO_AO_VERSION_MINOR 1
typedef struct csi_ao_chn_state {
uint32_t chntotalnum;
uint32_t chnfreenum;
uint32_t chnbusynum;
}csi_ao_chn_state_s;
typedef enum csi_audio_fade_rate {
AUIDO_FADE_RATE_1 = 0,
AUIDO_FADE_RATE_2 = 1,
AUIDO_FADE_RATE_4 = 2,
AUIDO_FADE_RATE_8 = 3,
AUIDO_FADE_RATE_16 = 4,
AUIDO_FADE_RATE_32 = 5,
AUIDO_FADE_RATE_64 = 6,
AUIDO_FADE_RATE_128 = 7,
AUIDO_FADE_RATE_BUTT
}csi_audio_fade_rate_e;
typedef struct csi_audio_fade {
bool fade;
csi_audio_fade_rate_e fadeinrate;
csi_audio_fade_rate_e fadeoutrate;
}csi_audio_fade_s;
typedef struct csi_ao_vqe_config {
int32_t hpfopen;
int32_t anropen;
int32_t agcopen;
int32_t eqopen;
int32_t worksamplerate;
int32_t framesample;
csi_vqe_workstate_e workstate;
csi_audio_hpf_config_s hpfcfg;
csi_audio_anr_config_s anrcfg;
csi_audio_agc_config_s agccfg;
csi_audio_eq_config_s eqcfg;
}csi_ao_vqe_config_s;
int32_t csi_ao_get_version(csi_api_version_u *version);
int32_t csi_ao_query_list(csi_ao_infos_s *infos);
int32_t csi_ao_setpubattr(int32_t aodev,csi_aio_attr_s *attr);
int32_t csi_ao_getpubattr(int32_t aodev,csi_aio_attr_s *attr);
int32_t csi_ao_enable(int32_t aodev);
int32_t csi_ao_disable(int32_t aodev);
int32_t csi_ao_enablechn(int32_t aodev,int32_t aochn);
int32_t csi_ao_disablechn(int32_t aodev,int32_t aochn);
int32_t csi_ao_sendframe(int32_t aodev,int32_t aochn,const csi_audio_frame_s *data,int32_t timeout);
int32_t csi_ao_enableresmp(int32_t aodev,int32_t aochn,csi_audio_sample_rate_e insamplerate);
int32_t csi_ao_disableresmp(int32_t aodev,int32_t aochn);
int32_t csi_ao_pausechn(int32_t aodev,int32_t aochn);
int32_t csi_ao_resumechn(int32_t aodev,int32_t aochn);
int32_t csi_ao_clearchnbuf(int32_t aodev,int32_t aochn);
int32_t csi_ao_querychnstat(int32_t aodev,int32_t aochn,csi_ao_chn_state_s *status);
int32_t csi_ao_settrackmode(int32_t aodev,csi_audio_track_mode_e trackmode);
int32_t csi_ao_gettrackmode(int32_t aodev,csi_audio_track_mode_e *trackmode);
int32_t csi_ao_setvolume(int32_t aodev,int32_t volume);
int32_t csi_ao_getvolume(int32_t aodev,int32_t *volume);
int32_t csi_ao_setmute(int32_t aodev,bool enable,csi_audio_fade_s *fade);
int32_t csi_ao_getmute(int32_t aodev,bool enable,csi_audio_fade_s *fade);
int32_t csi_ao_reset(int32_t aodev);
int32_t csi_ao_setvqeattr(int32_t aodev,int32_t aochn,csi_ao_vqe_config_s *vqeconfig);
int32_t csi_ao_getvqeattr(int32_t aodev,int32_t aochn,csi_ao_vqe_config_s *vqeconfig);
int32_t csi_ao_enablevqe(int32_t aodev,int32_t aochn);
int32_t csi_ao_disablevqe(int32_t aodev,int32_t aochn);
#endif

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: fuqian.zxr <fuqian.zxr@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_AUDIO_COMMON_H__
#define __CSI_AUDIO_COMMON_H__
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include "csi_common.h"
#define MAX_AUDIO_FILE_PATH_LEN 256
#define VQE_EQ_BAND_NUM 10
typedef enum csi_audio_sample_rate {
AUDIO_SAMPLE_RATE_8000 = 8000, /*8K samplerate*/
AUDIO_SAMPLE_RATE_12000 = 12000, /*12K samplerate*/
AUDIO_SAMPLE_RATE_11025 = 11025, /*11.025K samplerate*/
AUDIO_SAMPLE_RATE_16000 = 16000, /*16K samplerate*/
AUDIO_SAMPLE_RATE_22050 = 22050, /*22.05k samplerate*/
AUDIO_SAMPLE_RATE_24000 = 24000, /*24K samplerate*/
AUDIO_SAMPLE_RATE_32000 = 32000, /*32K samplerate*/
AUDIO_SAMPLE_RATE_44100 = 44100, /*44.1K samplerate*/
AUDIO_SAMPLE_RATE_48000 = 48000, /*48K samplerate*/
AUDIO_SAMPLE_RATE_64000 = 64000, /*64K samplerate*/
AUDIO_SAMPLE_RATE_96000 = 96000, /*96K samplerate*/
AUDIO_SAMPLE_RATE_BUTT,
}csi_audio_sample_rate_e;
typedef enum csi_audio_bit_width {
AUDIO_BIT_WIDTH_8 = 0, /*8bit width*/
AUDIO_BIT_WIDTH_16 = 1, /*16bit width*/
AUDIO_BIT_WIDTH_24 = 2, /*24bit width*/
AUDIO_BIT_WIDTH_BUTT,
}csi_audio_bit_width_e;
typedef enum csi_audio_mode {
AIO_MODE_I2S_MASTER = 0, /* AIO I2S master mode */
AIO_MODE_I2S_SLAVE, /* AIO I2S slave mode */
AIO_MODE_PCM_SLAVE_STD, /* AIO PCM slave standard mode */
AIO_MODE_PCM_SLAVE_NSTD, /* AIO PCM slave non-standard mode */
AIO_MODE_PCM_MASTER_STD, /* AIO PCM master standard mode */
AIO_MODE_PCM_MASTER_NSTD, /* AIO PCM master non-standard mode */
AIO_MODE_BUTT,
}csi_audio_mode_e;
typedef enum csi_audio_sound_mode {
AUDIO_SOUND_MODE_MONO = 0, /*mono*/
AUDIO_SOUND_MODE_STEREO = 1, /*stereo*/
AUDIO_SOUND_MODE_BUTT
}csi_audio_sound_mode_e;
typedef enum csi_auido_i2stype {
AIO_I2STYPE_INNERCODEC = 0, /*AIO I2S connect inner audio CODEC*/
AIO_I2STYPE_INNERHDMI, /*AIO I2S connect inner HDMI*/
AIO_I2STYPE_EXTERN, /*AIO I2S connect extern hardware*/
}csi_auido_i2stype_e;
typedef struct csi_aio_attr {
csi_audio_sample_rate_e samplerate; /*sample rate*/
csi_audio_bit_width_e bitwidth; /*bitwidth*/
csi_audio_mode_e workmode; /*master or slave mode*/
csi_audio_sound_mode_e soundmode; /*mono or steror*/
uint32_t exflag;
uint32_t frmnum;
uint32_t pt_num_per_frm;
uint32_t chncnt;
csi_auido_i2stype_e i2stype;
}csi_aio_attr_s;
typedef struct csi_audio_frame {
csi_audio_bit_width_e bitwidth;
csi_audio_sound_mode_e soundmode;
void *viraddr[2];
uint32_t phyaddr[2];
uint64_t timestamp; /*audio frame timestamp*/
uint32_t seq; /*audio frame seq*/
uint32_t len; /*data length per channel in frame*/
uint32_t poolid[2];
}csi_audio_frame_s;
typedef enum csi_audio_track_mode {
AUDIO_TRACK_NORMAL = 0,
AUDIO_TRACK_BOTH_LEFT = 1,
AUDIO_TRACK_BOTH_RIGHT = 2,
AUDIO_TRACK_EXCHANGE = 3,
AUDIO_TRACK_MIX = 4,
AUDIO_TRACK_LEFT_MUTE = 5,
AUDIO_TRACK_RIGHT_MUTE = 6,
AUDIO_TRACK_BOTH_MUTE = 7,
AUDIO_TRACK_BUTT,
}csi_audio_track_mode_e;
typedef struct csi_audio_save_file_info {
bool cfg;
char filepath[MAX_AUDIO_FILE_PATH_LEN];
char filename[MAX_AUDIO_FILE_PATH_LEN];
uint32_t filesize;
}csi_audio_save_file_info_s;
typedef struct csi_audio_file_status {
bool saving;
}csi_audio_file_status_s;
typedef enum csi_vqe_workstate {
VQE_WORKSTATE_COMMON = 0,
VQE_WORKSTATE_MUSIC = 1,
VQE_WORKSTATE_NOISY = 2
}csi_vqe_workstate_e;
typedef enum csi_audio_hpf_freq {
AUDIO_HPF_FREQ_80 = 80, /*80HZ*/
AUDIO_HPF_FREQ_120 = 120, /*120Hz*/
AUDIO_HPF_FREQ_150 = 150, /*150Hz*/
AUDIO_HPF_FREQ_BUTT,
}csi_audio_hpf_freq_e;
typedef struct csi_audio_hpf_config {
bool usrmode;
csi_audio_hpf_freq_e hpffreq;
}csi_audio_hpf_config_s;
typedef struct csi_audio_anr_config {
bool usrmode;
int16_t nrintensity;
int16_t noisedbthr;
int8_t sp_pro_switch;
int32_t reserved;
}csi_audio_anr_config_s;
typedef struct csi_audio_agc_config {
bool usrmode;
int8_t target_level;
int8_t noise_floor;
int8_t maxgain;
int8_t adjustspeed;
int8_t improvesnr;
int8_t usehighpassfilt;
int8_t outputmode;
int16_t noisesupswitch;
int32_t reserved;
}csi_audio_agc_config_s;
typedef struct csi_audio_eq_config {
int8_t gaindb[VQE_EQ_BAND_NUM];
int32_t reserved;
}csi_audio_eq_config_s;
typedef enum {
PT_PCMU = 0,
PT_1016 = 1,
PT_BUTT
}PAYLOAD_TYPE_E;
typedef struct csi_audio_stream {
uint8_t *stream; /*the virtual address of stream*/
uint32_t phyaddr; /*the physics address of stream*/
uint32_t len; /*stream length,by bytes*/
uint64_t timestamp; /*frame time stamp*/
uint32_t seq; /*frame seq,if stream is not a valid frame 0*/
}csi_audio_stream_s;
#endif

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: fuqian.zxr <fuqian.zxr@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_AUDIO_DEC_H__
#define __CSI_AUDIO_DEC_H__
#include "csi_audio_common.h"
#define CSI_AUDIO_DEC_VERSION_MAJOR 0
#define CSI_AUDIO_DEC_VERSION_MINOR 1
typedef enum csi_adec_mode {
ADEC_MODE_PACK = 0,
ADEC_MODE_STREAM,
ADEC_MODE_BUTT
}csi_adec_mode_e;
typedef struct csi_adec_ch_attr {
PAYLOAD_TYPE_E type;
uint32_t bufsize;
csi_adec_mode_e mode;
void *value;
}csi_adec_ch_attr_s;
typedef struct csi_adec_decoder {
PAYLOAD_TYPE_E type;
char name[16];
int32_t (*openendecoder)(void *decoderattr,void **decoder);
int32_t (*decoderfrm)(void *decoder,uint8_t **inbuf,int32_t leftbyte,uint16_t *outbuf,uint32_t *outlen,uint32_t *chns);
int32_t (*getfrminfo)(void *decoder,void *info);
int32_t (*closedecoder)(void *decoder);
int32_t (*resetdecoder)(void *decoder);
}csi_adec_decoder_s;
typedef struct csi_audio_frame_info {
csi_audio_frame_s *frame;
uint32_t id;
}csi_audio_frame_info_s;
int32_t csi_adec_get_version(csi_api_version_u *version);
int32_t csi_adec_create(int32_t adchn,csi_adec_ch_attr_s);
int32_t csi_adec_destroy(int32_t adchn);
int32_t csi_adec_sendstream(int32_t adchn,const csi_audio_stream_s *stream, bool block);
int32_t csi_adec_clearchnbuf(int32_t adchn);
int32_t csi_adec_registerdecoder(int32_t handle,csi_adec_decoder_s *decoder);
int32_t csi_adec_unregisterdecoder(int32_t hanbdle);
int32_t csi_adec_getframe(int32_t adchn,csi_audio_frame_info_s *frameinfo,bool block);
int32_t csi_adec_releaseframe(int32_t adchn,csi_audio_frame_info_s *frameinfo);
int32_t csi_adec_sendendofstream(int adchn,bool instant);
#endif

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: fuqian.zxr <fuqian.zxr@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_AUDIO_ENC_H__
#define __CSI_AUDIO_ENC_H__
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include "csi_audio_common.h"
#define CSI_AUDIO_ENC_VERSION_MAJOR 0
#define CSI_AUDIO_ENC_VERSION_MINOR 1
typedef struct csi_aenc_chn_attr
{
PAYLOAD_TYPE_E type;
uint32_t numperfrm;
uint32_t buffersize;
}csi_aenc_chn_attr_s;
typedef struct csi_aec_frame {
csi_audio_frame_s refframe;
bool valid;
bool sysbind;
}csi_aec_frame_s;
typedef struct csi_aenc_encode {
PAYLOAD_TYPE_E type;
uint32_t maxfrmlen;
char name[16];
int32_t (*openencoder)(void *encoderattr,void **encoder);
int32_t (*encoderfrm)(void *encoder,const csi_audio_frame_s *data,uint8_t *outbuf,uint32_t *outlen);
int32_t (*closeencoder)(void *encoder);
}csi_aenc_encode_s;
int32_t csi_adec_get_version(csi_api_version_u *version);
int32_t csi_aenc_createchn(int32_t aechn,const csi_aenc_chn_attr_s attr);
int32_t csi_aenc_destroychn(int32_t aechn);
int32_t csi_aenc_sendframe(int32_t aechn,const csi_audio_frame_s *frm,const csi_aec_frame_s *aecfrm);
int32_t csi_aenc_getstream(int32_t aechn,csi_audio_stream_s *stream,int32_t timeout);
int32_t csi_aenc_releasestream(int32_t aechn,const csi_audio_stream_s *stream);
int32_t csi_aenc_getfd(int32_t aechn);
int32_t csi_aenc_registerencoder(int32_t handle,csi_aenc_encode_s *encoder);
int32_t csi_aenc_unregisterencoder(int32_t handle);
int32_t csi_aenc_savefile(int32_t aechn,csi_audio_save_file_info_s *savefileinfo);
int32_t csi_aenc_queryfilestatus(int32_t aechn,csi_audio_file_status_s *filestatus);
int32_t csi_aec_getstreambufinfo(int32_t aechn,uint32_t *physaddr,uint32_t *size);
#endif

297
include/hal/csi_camera.h Normal file
View File

@@ -0,0 +1,297 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_CAMERA_H__
#define __CSI_CAMERA_H__
#include <time.h>
#include <csi_common.h>
#include <csi_camera_property.h>
#include <csi_camera_frame.h>
#include <csi_frame_ex.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Camera logical parts are below, including: input sensor and output channel
* @------------------------------@
* | Camera Settings _____|______ Channel Settings
* | =================== | | =====================
* | Exposure | channel[0] | configuration: width/height, pix_fmt
* | R/G/B Gain |_____ ______| ---> Channel Events
* | HDR mode _____|______
* | ...... | |
* | | channel[1] | configuration: width/height, pix_fmt
* | |_____ ______| ---> Channel Events
* | _____|______
* | | |
* | | channel[n] | configuration: width/height, pix_fmt
* | |_____ ______| ---> Channel Events
* | CAMERA |
* @------------------------------@ ===> Camera Events (sensor, error, warning...)
*/
#define CSI_CAMERA_VERSION_MAJOR 0
#define CSI_CAMERA_VERSION_MINOR 2
#define CSI_CAMERA_NAME_MAX_LEN 32
typedef void *csi_cam_handle_t;
typedef void *csi_cam_event_handle_t;
typedef struct csi_cam_handle_info {
int idx;
} csi_cam_handle_info_t;
#define MAX_FRAME_COUNT 1024
typedef enum csi_frame_status_type {
CSI_FRAME_IDLE = 1,
CSI_FRAME_WORKING = 2,
CSI_FRAME_READY = 3,
CSI_FRAME_DISPATCHED = 4,
} csi_frame_status_type_e;
typedef struct frame_channel_info {
unsigned char *frame_bufs[MAX_FRAME_COUNT];
int frame_status[MAX_FRAME_COUNT];
int refcount[MAX_FRAME_COUNT];
int frame_cnt;
csi_frame_s frame[MAX_FRAME_COUNT];
} frame_channel_info_s;
typedef struct camera_frame_info {
unsigned char *frame_bufs;
int frame_status;
} camera_frame_info_s;
#define CSI_CAMERA_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */
#define CSI_CAMERA_CAP_META_CAPTURE 0x00800000 /* Is a metadata capture device */
typedef struct csi_camera_info {
char camera_name[CSI_CAMERA_NAME_MAX_LEN];
char device_name[CSI_CAMERA_NAME_MAX_LEN];
char bus_info[32]; /* e.g. "MIPI-CSI" */
unsigned int capabilities; /* bit mask of CSI_CAMERA_CAP_xx */
} csi_camera_info_s;
#define CSI_CAMERA_MAX_COUNT 16
typedef struct csi_camera_infos {
unsigned int count;
csi_camera_info_s info[CSI_CAMERA_MAX_COUNT];
} csi_camera_infos_s;
#define CSI_CAMERA_MODE_MAX_COUNT 16
typedef struct csi_camera_modes {
int count;
struct {
int mode_id;
char description[128];
} modes[CSI_CAMERA_MODE_MAX_COUNT];
} csi_camera_modes_s;
typedef struct csi_camera_mode_cfg {
int mode_id;
char *calibriation; /* set NULL to use default in system */
char *lib3a; /* set NULL to use default in system */
} csi_camera_mode_cfg_s;
typedef enum csi_camera_property_type {
CSI_CAMERA_PROPERTY_TYPE_INTEGER = 1,
CSI_CAMERA_PROPERTY_TYPE_BOOLEAN = 2,
CSI_CAMERA_PROPERTY_TYPE_ENUM = 3,
CSI_CAMERA_PROPERTY_TYPE_STRING = 7,
CSI_CAMERA_PROPERTY_TYPE_BITMASK = 8,
} csi_camera_property_type_e;
typedef union csi_camera_property_data {
bool bool_value;
int int_value;
int enum_value;
uint32_t bitmask_value;
char str_value[32];
} csi_camera_property_data_u;
typedef struct csi_camera_property_description {
unsigned int id; /* CSI_CAMERA_PID_xx */
csi_camera_property_type_e type; /* data type */
char name[32]; /* Whatever */
int minimum; /* Note signedness */
int maximum;
int step;
csi_camera_property_data_u default_value;
csi_camera_property_data_u value; /*current value*/
unsigned int flags;
unsigned int reserved[2];
} csi_camera_property_description_s;
typedef struct csi_camera_property {
unsigned int id;
csi_camera_property_type_e type; /* data type */
csi_camera_property_data_u value;
} csi_camera_property_s;
typedef struct csi_camera_properties {
unsigned int count;
csi_camera_property_s *property;
} csi_camera_properties_s;
typedef enum csi_camera_channel_id {
CSI_CAMERA_CHANNEL_0 = 0,
CSI_CAMERA_CHANNEL_1,
CSI_CAMERA_CHANNEL_2,
CSI_CAMERA_CHANNEL_3,
CSI_CAMERA_CHANNEL_4,
CSI_CAMERA_CHANNEL_5,
CSI_CAMERA_CHANNEL_6,
CSI_CAMERA_CHANNEL_7,
CSI_CAMERA_CHANNEL_MAX_COUNT
} csi_camera_channel_id_e;
typedef enum csi_camera_channel_status {
CSI_CAMERA_CHANNEL_INVALID = -1, /* channel can't be openned */
CSI_CAMERA_CHANNEL_CLOSED,
CSI_CAMERA_CHANNEL_OPENED,
CSI_CAMERA_CHANNEL_RUNNING,
CSI_CAMERA_CHANNEL_EXCEPTION,
} csi_camera_channel_status_e;
typedef enum csi_camera_channel_capture_type {
CSI_CAMERA_CHANNEL_CAPTURE_VIDEO = (1 << 0),
CSI_CAMERA_CHANNEL_CAPTURE_META = (1 << 1),
} csi_camera_channel_capture_type_e;
typedef struct csi_camera_channel_cfg {
csi_camera_channel_id_e chn_id;
unsigned int capture_type; /* bitmask of: csi_camera_channel_capture_type_e */
unsigned int frm_cnt;
csi_img_format_t img_fmt;
csi_img_type_e img_type;
unsigned int meta_fields; /* bitmask of: csi_camera_meta_id_e */
csi_camera_channel_status_e status;
} csi_camera_channel_cfg_s;
typedef enum csi_camera_event_type {
CSI_CAMERA_EVENT_TYPE_INVALID = -1,
CSI_CAMERA_EVENT_TYPE_CAMERA,
CSI_CAMERA_EVENT_TYPE_CHANNEL0,
CSI_CAMERA_EVENT_TYPE_CHANNEL1,
CSI_CAMERA_EVENT_TYPE_CHANNEL2,
CSI_CAMERA_EVENT_TYPE_CHANNEL3,
CSI_CAMERA_EVENT_TYPE_CHANNEL4,
CSI_CAMERA_EVENT_TYPE_CHANNEL5,
CSI_CAMERA_EVENT_TYPE_CHANNEL6,
CSI_CAMERA_EVENT_TYPE_CHANNEL7,
} csi_camera_event_type_e;
typedef enum csi_camera_event_id {
CSI_CAMERA_EVENT_WARNING = 1 << 0,
CSI_CAMERA_EVENT_ERROR = 1 << 1,
CSI_CAMERA_EVENT_SENSOR_FIRST_IMAGE_ARRIVE = 1 << 2,
CSI_CAMERA_EVENT_ISP_3A_ADJUST_READY = 1 << 3,
CSI_CAMERA_EVENT_MAX_COUNT = 32
} csi_camera_event_id_e;
typedef enum csi_camera_channel_event_id {
CSI_CAMERA_CHANNEL_EVENT_FRAME_READY = 1 << 0,
CSI_CAMERA_CHANNEL_EVENT_FRAME_PUT = 1 << 1,
CSI_CAMERA_CHANNEL_EVENT_OVERFLOW = 1 << 2,
CSI_CAMERA_CHANNEL_EVENT_MAX_COUNT = 32
} csi_camera_channel_event_id_e;
typedef struct csi_camera_event_subscription {
csi_camera_event_type_e type;
unsigned int id; /* bitmasks */
} csi_camera_event_subscription_s;
typedef struct csi_camera_event {
csi_camera_event_type_e type;
unsigned int id;
struct timespec timestamp;
union {
char bin[128];
};
} csi_camera_event_s;
int csi_camera_get_version(csi_api_version_u *version);
int csi_camera_query_list(csi_camera_infos_s *infos);
int csi_camera_open(csi_cam_handle_t *cam_handle, const char *device_name);
int csi_camera_close(csi_cam_handle_t cam_handle);
int csi_camera_get_modes(csi_cam_handle_t cam_handle,
csi_camera_modes_s *modes);
int csi_camera_set_mode(csi_cam_handle_t cam_handle,
csi_camera_mode_cfg_s *cfg);
int csi_camera_get_io_pattern(csi_cam_handle_t cam_handle, int *pattern);
int csi_camera_get_frame_config(csi_cam_handle_t cam_handle, csi_img_format_t *img_fmt, csi_frame_config_s *frm_cfg);
int csi_camera_set_frame_config(csi_cam_handle_t cam_handle, csi_img_format_t *img_fmt, csi_frame_config_s *frm_cfg);
int csi_sensor_enable_colobar(csi_cam_handle_t cam_handle, int en);
int csi_camera_query_property(csi_cam_handle_t cam_handle,
csi_camera_property_description_s *desc);
int csi_camera_get_property(csi_cam_handle_t cam_handle,
csi_camera_properties_s *properties);
int csi_camera_set_property(csi_cam_handle_t cam_handle,
csi_camera_properties_s *properties);
int csi_camera_channel_open(csi_cam_handle_t cam_handle,
csi_camera_channel_cfg_s *cfg);
int csi_camera_channel_close(csi_cam_handle_t cam_handle,
csi_camera_channel_id_e chn_id);
int csi_camera_channel_query(csi_cam_handle_t cam_handle,
csi_camera_channel_cfg_s *cfg);
int csi_camera_get_frame_count(csi_cam_handle_t cam_handle,
csi_camera_channel_id_e chn_id);
int csi_camera_get_frame(csi_cam_handle_t cam_handle,
csi_camera_channel_id_e chn_id,
csi_frame_s *frame, int timeout);
int csi_camera_put_frame(csi_frame_s *frame);
int csi_camera_dequeue_frame(csi_cam_handle_t cam_handle,
csi_camera_channel_id_e chn_id,
csi_frame_ex_s **frame,
int timeout);
int csi_camera_enqueue_frame(csi_cam_handle_t cam_handle,
csi_camera_channel_id_e chn_id,
csi_frame_ex_s *frame);
int csi_camera_create_event(csi_cam_event_handle_t *event_handle,
csi_cam_handle_t cam_handle);
int csi_camera_destory_event(csi_cam_event_handle_t event_handle);
int csi_camera_subscribe_event(csi_cam_event_handle_t event_handle,
csi_camera_event_subscription_s *subscribe);
int csi_camera_unsubscribe_event(csi_cam_event_handle_t event_handle,
csi_camera_event_subscription_s *subscribe);
int csi_camera_get_event(csi_cam_event_handle_t event_handle,
csi_camera_event_s *event,
int timeout);
int csi_camera_channel_start(csi_cam_handle_t cam_handle,
csi_camera_channel_id_e chn_id);
int csi_camera_channel_stop(csi_cam_handle_t cam_handle,
csi_camera_channel_id_e chn_id);
#ifdef __cplusplus
}
#endif
#endif /* __CSI_CAMERA_H__ */

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_CAMERA_FRAME_H__
#define __CSI_CAMERA_FRAME_H__
#include <stddef.h>
#include <stdbool.h>
#include <sys/time.h>
#include <csi_frame.h>
#define CSI_CAMERA_META_MAX_LEN 1024
typedef enum csi_camera_meta_id {
CSI_CAMERA_META_ID_CAMERA_NAME = (1<<0), /* str_value */
CSI_CAMERA_META_ID_CHANNEL_ID = (1<<1), /* uint_value */
CSI_CAMERA_META_ID_FRAME_ID = (1<<2), /* uint_value: Re-Count from zero when start() */
CSI_CAMERA_META_ID_TIMESTAMP = (1<<3), /* time_value: Get from gettimeofday() */
CSI_CAMERA_META_ID_HDR = (1<<4), /* bool_value */
} csi_camera_meta_id_e;
#define CSI_CAMERA_META_NO_FIELD 0
#define CSI_CAMERA_META_DEFAULT_FIELDS (CSI_CAMERA_META_ID_CAMERA_NAME | \
CSI_CAMERA_META_ID_CHANNEL_ID | \
CSI_CAMERA_META_ID_FRAME_ID | \
CSI_CAMERA_META_ID_TIMESTAMP)
typedef struct csi_camrea_meta_unit {
csi_camera_meta_id_e id;
csi_meta_value_type_e type;
union {
bool bool_value;
int int_value;
unsigned int uint_value;
char str_value[32];
struct timeval time_value;
};
} csi_camrea_meta_unit_s;
typedef struct csi_camera_meta {
unsigned int count;
size_t size;
csi_camrea_meta_unit_s *units; // Is meta_unit array head
} csi_camera_meta_s;
int csi_camera_frame_alloc_meta(csi_camera_meta_s **meta, int meta_count, size_t *meta_data_size);
int csi_camera_frame_free_meta(csi_camera_meta_s *meta);
int csi_camera_frame_get_meta_unit(csi_camrea_meta_unit_s *meta_unit,
csi_camera_meta_s *meta_data,
csi_camera_meta_id_e meta_field);
#endif /* __CSI_CAMERA_FRAME_H__ */

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_CAMERA_PLATFORM_SPEC_H__
#define __CSI_CAMERA_PLATFORM_SPEC_H__
#include <stdio.h>
#include <csi_camera.h>
/******************************************************************************/
/*********** Platform Spec in Enum ********************************************/
/******************************************************************************/
#define CAMERA_PROPERTY_MAX_ENUM_COUNT 16
typedef struct camera_support_enums {
int count;
int enums[CAMERA_PROPERTY_MAX_ENUM_COUNT];
} camera_spec_enums_s;
typedef enum camera_sepc_enums {
CAMERA_SPEC_ENUM_CHANNEL_PIX_FMT,
CAMERA_SPEC_ENUM_CHANNEL_IMG_TYPE,
CAMERA_SPEC_ENUM_CAMERA_EVENT_TYPES,
CAMERA_SPEC_ENUM_CHANNEL_EVENT_TYPES,
/* Camera Properties below */
CAMERA_SPEC_ENUM_CAMERA_EXPOSURE_MODES = CSI_CAMERA_PID_EXPOSURE_MODE,
} camera_sepc_enums_e;
const camera_spec_enums_s *camera_spec_get_enum_array(int property_id);
/******************************************************************************/
/*********** Platform Spec in Bitmask *****************************************/
/******************************************************************************/
#define CAMERA_PROPERTY_MAX_BITMASK_COUNT 32
typedef struct camera_support_bitmasks {
int count;
int bitmask[CAMERA_PROPERTY_MAX_BITMASK_COUNT];
} camera_spec_bitmasks_t;
typedef enum camera_sepc_bitmasks {
CAMERA_SPEC_BITMAKS_CHANNEL_CAPTURE_TYPE,
CAMERA_SPEC_BITMAKS_CHANNEL_META_TYPE,
/* Camera Properties below */
CAMERA_SPEC_BITMAKS_CAMERA_3A_LOCK = CSI_CAMERA_PID_3A_LOCK,
} camera_sepc_bitmasks_e;
const camera_spec_bitmasks_t *camera_spec_get_bitmask_array(int property_id);
#endif /* __CSI_CAMERA_PLATFORM_SPEC_H__ */

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_CAMERA_PROPERTY_H__
#define __CSI_CAMERA_PROPERTY_H__
/* Camera Property ID */
#define CSI_CAMERA_PID_BASE (0x009a0000 | 0x900)
#define CSI_CAMERA_FLAG_NEXT_CTRL 0x80000000
/* image processing releated */
#define CSI_CAMERA_PID_HFLIP (CSI_CAMERA_PID_BASE + 0x1)
#define CSI_CAMERA_PID_VFLIP (CSI_CAMERA_PID_BASE + 0x2)
#define CSI_CAMERA_PID_ROTATE (CSI_CAMERA_PID_BASE + 0x3)
/* exposure related */
#define CSI_CAMERA_PID_EXPOSURE_MODE (CSI_CAMERA_PID_BASE + 0x11)
enum CSI_CAMERA_EXPOSURE_MODE {
CSI_CAMERA_EXPOSURE_MODE_AUTO = 0,
CSI_CAMERA_EXPOSURE_MANUAL = 1,
CSI_CAMERA_EXPOSURE_SHUTTER_PRIORITY = 2,
CSI_CAMERA_EXPOSURE_APERTURE_PRIORITY = 3,
};
#define CSI_CAMERA_PID_EXPOSURE_ABSOLUTE (CSI_CAMERA_PID_BASE + 0x12)
#define CSI_CAMERA_PID_EXPOSURE_AUTO_PRIORITY (CSI_CAMERA_PID_BASE + 0x13)
#define CSI_CAMERA_PID_EXPOSURE_BIAS (CSI_CAMERA_PID_BASE + 0x14)
#define CSI_CAMERA_PID_EXPOSURE_METERING (CSI_CAMERA_PID_BASE + 0x15)
enum CSI_CAMERA_PID_EXPOSURE_METERING_MODE {
CSI_CAMERA_EXPOSURE_METERING_AVERAGE = 0,
CSI_CAMERA_EXPOSURE_METERING_CENTER_WEIGHTED = 1,
CSI_CAMERA_EXPOSURE_METERING_SPOT = 2,
CSI_CAMERA_EXPOSURE_METERING_MATRIX = 3,
};
/* Focus related */
#define CSI_CAMERA_PID_FOCUS_ABSOLUTE (CSI_CAMERA_PID_BASE + 0x21)
#define CSI_CAMERA_PID_FOCUS_RELATIVE (CSI_CAMERA_PID_BASE + 0x22)
#define CSI_CAMERA_PID_FOCUS_AUTO (CSI_CAMERA_PID_BASE + 0x23)
#define CSI_CAMERA_PID_AUTO_FOCUS_START (CSI_CAMERA_PID_BASE + 0x24)
#define CSI_CAMERA_PID_AUTO_FOCUS_STOP (CSI_CAMERA_PID_BASE + 0x25)
#define CSI_CAMERA_PID_AUTO_FOCUS_STATUS (CSI_CAMERA_PID_BASE + 0x26)
#define CSI_CAMERA_AUTO_FOCUS_STATUS_IDLE (1<<0)
#define CSI_CAMERA_AUTO_FOCUS_STATUS_BUSY (1<<1)
#define CSI_CAMERA_AUTO_FOCUS_STATUS_REACHED (1<<2)
#define CSI_CAMERA_AUTO_FOCUS_STATUS_FAILED (1<<3)
/* 3A misc */
#define CSI_CAMERA_PID_AUTO_PRESET_WHITE_BALANCE (CSI_CAMERA_PID_BASE + 0x31)
enum CSI_CAMERA_AUTO_PRESET_WHITE_BALANCE_MODE {
CSI_CAMERA_WHITE_BALANCE_MANUAL = 0,
CSI_CAMERA_WHITE_BALANCE_AUTO = 1,
CSI_CAMERA_WHITE_BALANCE_CUSTOM1 = 2,
CSI_CAMERA_WHITE_BALANCE_CUSTOM2 = 3,
};
#define CSI_CAMERA_PID_3A_LOCK (CSI_CAMERA_PID_BASE + 0x32)
#define CSI_CAMERA_LOCK_EXPOSURE (1 << 0)
#define CSI_CAMERA_LOCK_WHITE_BALANCE (1 << 1)
#define CSI_CAMERA_LOCK_FOCUS (1 << 2)
/* Gain */
#define CSI_CAMERA_PID_RED_GAIN (CSI_CAMERA_PID_BASE + 0x41)
#define CSI_CAMERA_PID_GREEN_GAIN (CSI_CAMERA_PID_BASE + 0x42)
#define CSI_CAMERA_PID_BLUE_GAIN (CSI_CAMERA_PID_BASE + 0x43)
#define CSI_CAMERA_PID_WIDE_DYNAMIC_RANGE (CSI_CAMERA_PID_BASE + 0x44)
#define CSI_CAMERA_PID_ZOOM_ABSOLUTE (CSI_CAMERA_PID_BASE + 0x45)
#define CSI_CAMERA_PID_ZOOM_RELATIVE (CSI_CAMERA_PID_BASE + 0x46)
#define CSI_CAMERA_PID_ZOOM_CONTINOUS (CSI_CAMERA_PID_BASE + 0x47)
/* PAN & TILT */
#define CSI_CAMERA_PID_PAN_RELATIVE (CSI_CAMERA_PID_BASE + 0x51)
#define CSI_CAMERA_PID_TILT_RELATIVE (CSI_CAMERA_PID_BASE + 0x52)
#define CSI_CAMERA_PID_PAN_ABSOLUTE (CSI_CAMERA_PID_BASE + 0x53)
#define CSI_CAMERA_PID_TILT_ABSOLUTE (CSI_CAMERA_PID_BASE + 0x54)
#define CSI_CAMERA_PID_PAN_RESET (CSI_CAMERA_PID_BASE + 0x55)
#define CSI_CAMERA_PID_TILT_RESET (CSI_CAMERA_PID_BASE + 0x56)
/* misc enhance */
#define CSI_CAMERA_PID_HDR_MODE (CSI_CAMERA_PID_BASE + 0x61)
#define CSI_CAMERA_PID_BAND_STOP_FILTER (CSI_CAMERA_PID_BASE + 0x62)
#define CSI_CAMERA_PID_IMAGE_STABILIZATION (CSI_CAMERA_PID_BASE + 0x63)
#endif /* __CSI_CAMERA_PROPERTY_H__ */

68
include/hal/csi_common.h Normal file
View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_COMMON_H__
#define __CSI_COMMON_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
typedef union csi_api_version {
struct {
uint16_t minor;
uint16_t major;
};
uint32_t version;
} csi_api_version_u;
typedef struct csi_size {
uint32_t width;
uint32_t height;
} csi_size_s;
typedef struct csi_rect {
uint32_t pos_x;
uint32_t pos_y;
uint32_t width;
uint32_t height;
} csi_rect_s;
enum {
CSI_IO_PATTERN_INTERNAL_MEMORY = 0x01, /* Internal preparation IO memory mode */
CSI_IO_PATTERN_EXTERNAL_MEMORY = 0x02 /* External preparation IO memory mode */
};
typedef enum csi_common_err_code {
CSI_SUCCESS,
CSI_ERR_BAD_PARAM,
CSI_ERR_NOT_SUPPORT,
CSI_ERR_BUSY,
CSI_ERR_OUT_OF_MEMORY,
CSI_ERR_NEED_MORE_DATA,
CSI_ERR_NEED_MORE_IO_FRAME,
CSI_ERR_TIMEOUT,
CSI_ERR_WAIT
} csi_common_err_code_e;
int32_t csi_hal_init();
int32_t csi_hal_deinit();
#ifdef __cplusplus
}
#endif
#endif /* __CSI_COMMON_H__ */

54
include/hal/csi_fce.h Normal file
View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright(C) 2021 Alibaba Communications Inc.
* Author: David Li <liyong.li@alibaba-inc.com>
*/
#ifndef _FCE_HAL_H_
#define _FCE_HAL_H_
#ifdef __cplusplus
extern "C"{
#endif
#include "fce_cfg.h"
enum FCE_EVENT {
FCE_EVENT_COMPLETE = 0,
FCE_EVENT_PAUSE,
FCE_EVENT_BUSERR,
FCE_EVENT_TIMEOUT,
FCE_EVENT_UNDEFMSG,
FCE_EVENT_SOCKERR,
FCE_EVENT_OTHER
};
typedef void *csi_fce_handle_t;
typedef void *csi_fce_sock_handle_t;
int csi_fce_open(csi_fce_handle_t *fce_handle, char *name);
int csi_fce_close(csi_fce_handle_t fce_handle);
int csi_fce_query_result_cnt(csi_fce_handle_t fce_handle, unsigned int *cnt);
int csi_fce_set_result_cnt(csi_fce_handle_t fce_handle, unsigned int *cnt);
int csi_fce_set_attr(csi_fce_handle_t fce_handle, struct fce_cfg *cfg);
int csi_fce_get_attr(csi_fce_handle_t fce_handle, struct fce_cfg *cfg);
int csi_fce_do_compare(csi_fce_handle_t fce_handle, struct target_vector *target_vect);
int csi_fce_get_result(csi_fce_handle_t fce_handle, struct top_result *top_buf);
int csi_fce_suspend(csi_fce_handle_t fce_handle);
int csi_fce_resume(csi_fce_handle_t fce_handle);
unsigned long csi_fce_create_featurelib(csi_fce_handle_t fce_handle, unsigned int size);
int csi_fce_release_featurelib(csi_fce_handle_t fce_handle, unsigned long offset);
int csi_fce_config_init(struct fce_cfg *cfg);
int csi_fce_check_result(struct top_result *res1, struct top_result *res2);
int csi_fce_init_sock(csi_fce_sock_handle_t *sock_handle, unsigned long timeout_ms);
int csi_fce_release_sock(csi_fce_sock_handle_t sock_handle);
enum FCE_EVENT csi_fce_waitevent(csi_fce_sock_handle_t sock_handle);
#ifdef __cplusplus
}
#endif
#endif // #ifndef _FCE_HAL_H_

94
include/hal/csi_fce_cfg.h Normal file
View File

@@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright(C) 2021 Alibaba Communications Inc.
* Author: David Li <liyong.li@alibaba-inc.com>
*/
#ifndef FCE_CFG_H
#define FCE_CFG_H
#ifdef __cplusplus
extern "C"{
#endif
#define MAX_BASE_NUM 1000000
#define TOPREG_CNT 8
#define TARGET_VECTOR_CNT 64
#define PREPRO_VECTOR_CNT 64
#define BITS_PER_BYTE 8
enum FCE_BASE_NUM {
BASENUM_1 = 0,
BASENUM_10,
BASENUM_1w,
BASENUM_5w,
BASENUM_10w,
BASENUM_20w,
BASENUM_50w,
BASENUM_100w,
BASENUM_MAX = BASENUM_100w,
};
enum FCE_DIMENSION {
DIM_128 = 0,
DIM_160,
DIM_192,
DIM_224,
DIM_256,
DIM_MAX = DIM_256,
};
enum FCE_INT_WIDTH {
INT_WIDTH_8 = 0,
INT_WIDTH_4,
INT_WIDTH_MAX = INT_WIDTH_4,
};
enum FCE_SIGN_SEL {
UNSIGN = 0,
SIGN,
SIGSEL_MAX = SIGN,
};
struct target_vector {
int value;
};
struct prepro_vector {
int value;
};
enum FCE_ENDIAN_SEL {
FCE_LIT_ENDIAN = 0,
FCE_BIG_ENDIAN,
FCE_ENDIAN_MAX = FCE_BIG_ENDIAN,
};
struct fce_cfg {
unsigned int base_num; // feature num in library, < MAX_BASE_NUM
// comparasion start address in feature library buffer, default is 0
unsigned long offset_base;
unsigned long saddr; // fill in kernel driver
enum FCE_DIMENSION dim; // dimension
enum FCE_INT_WIDTH width;
enum FCE_SIGN_SEL sigsel; // sign or unsign
unsigned int readnum; // number of target vector, unit byte
// data endian format of feature library
enum FCE_ENDIAN_SEL base_endian;
// data endian format of target feature vector for comparasion
enum FCE_ENDIAN_SEL target_endian;
// data endian format of xor operation on the feature library
enum FCE_ENDIAN_SEL prepro_endian;
struct prepro_vector prepro_vect[PREPRO_VECTOR_CNT]; // xor vector
};
struct top_result {
int match_value;
unsigned int match_index;
};
#ifdef __cplusplus
}
#endif
#endif // #ifndef FCE_CFG_H

156
include/hal/csi_frame.h Normal file
View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CSI_FRAME_H__
#define __CSI_FRAME_H__
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
/*
* CSI frame defination is below, including
*
* @-- [frm_id] ----------------@
* | __________ ___________ |
* | | | | | |
* | | img_info | | meta_info | |
* | |__________| |___________| |
* | |
* @------- csi_frame_s --------@
*/
#define CSI_IMAGE_MAX_PLANES 3
#define CSI_IMAGE_I420_PLANES 2
typedef enum csi_pixel_fmt {
CSI_PIX_FMT_I420, // YYYYYYYY UU VV, alias: YUV420P/YU12/IYUV
CSI_PIX_FMT_NV12, // YYYYYYYY UV UV, alias: YUV420SP
CSI_PIX_FMT_BGR,
CSI_PIX_FMT_RAW_8BIT,/*default no align*/
CSI_PIX_FMT_RAW_10BIT,
CSI_PIX_FMT_RAW_12BIT,
CSI_PIX_FMT_RAW_14BIT,
CSI_PIX_FMT_RAW_16BIT,
CSI_PIX_FMT_RGB_PLANAR_888,
CSI_PIX_FMT_RGB_INTEVLEAVED_888,
CSI_PIX_FMT_YUV_PLANAR_422,
CSI_PIX_FMT_YUV_PLANAR_420,
CSI_PIX_FMT_YUV_PLANAR_444,
CSI_PIX_FMT_YUV_SEMIPLANAR_422,
CSI_PIX_FMT_YUV_SEMIPLANAR_420,
CSI_PIX_FMT_YUV_SEMIPLANAR_444,
CSI_PIX_FMT_YUV_TEVLEAVED_422,
CSI_PIX_FMT_YUV_TEVLEAVED_420,
CSI_PIX_FMT_YUV_TEVLEAVED_444,
} csi_pixel_fmt_e;
typedef enum csi_color_gamut {
CSI_COLOR_GAMUT_DEFAULT = 0,
CSI_COLOR_GAMUT_BT601,
CSI_COLOR_GAMUT_BT709,
CSI_COLOR_GAMUT_BT2020,
} csi_color_gamut_e;
typedef enum csi_meta_type {
CSI_META_TYPE_SYSTEM,
CSI_META_TYPE_CAMERA,
CSI_META_TYPE_VDEC,
CSI_META_TYPE_GPU,
CSI_META_TYPE_G2D,
} csi_meta_type_e;
typedef enum csi_img_type {
CSI_IMG_TYPE_DMA_BUF, // memory allocated via dma-buf
CSI_IMG_TYPE_SYSTEM_CONTIG, // memory allocated via kmalloc
CSI_IMG_TYPE_CARVEOUT, // memory allocated from reserved memory
CSI_IMG_TYPE_UMALLOC, // memory allocated from user mode malloc
CSI_IMG_TYPE_SHM, // memory allocated from share memory(<sys/shm.h>)
} csi_img_type_e;
typedef enum csi_meta_value_type {
CSI_META_VALUE_TYPE_BOOL,
CSI_META_VALUE_TYPE_INT,
CSI_META_VALUE_TYPE_UINT,
CSI_META_VALUE_TYPE_STR,
CSI_META_VALUE_TYPE_TIMEVAL,
} csi_meta_value_type_e;
/*
* CSI frame config design
*
* line_stride -->|
* img_width -->| |
* _____________|___| __ start addr of frame/image, alignment (such as 4096)
* | | |
* | img_content | |
* |_____________|___| __ end addr of image, No alignment requirement
* | extra_data |
* |_________________| __ end addr of frame, No alignment requirement
*/
typedef struct csi_img_format {
uint32_t width;
uint32_t height;
csi_pixel_fmt_e pix_fmt;
} csi_img_format_t;
typedef struct {
int32_t stride_alignment; // should >= to the width of the image according to IP design
int32_t addr_alignment; // physical begin address alignment according to IP design
int32_t extra_size; // storaging platform private data according to IP design (meta data storage is suggested)
int32_t min_buffers_count; // minimum number of buffers required
} csi_frame_config_s; // New defined structure
typedef struct {
int fds; // stores in dma_buf memory(s)
unsigned long offset;
} cam_frame_dmabuf_t;
typedef struct csi_img {
csi_img_type_e type;
size_t size;
uint32_t width;
uint32_t height;
csi_pixel_fmt_e pix_format;
csi_color_gamut_e color_gamut;
uint32_t num_planes;
union {
cam_frame_dmabuf_t dmabuf[CSI_IMAGE_MAX_PLANES]; // stores in dma_buf memory(s)
int fds[CSI_IMAGE_MAX_PLANES]; // stores in dma_buf memory(s)
void *phy_addr[CSI_IMAGE_MAX_PLANES]; // stores in phy contigous memory(s)
void *usr_addr[CSI_IMAGE_MAX_PLANES]; // stores in usr contigous memory(s)
};
uint32_t strides[CSI_IMAGE_MAX_PLANES];
uint32_t offsets[CSI_IMAGE_MAX_PLANES];
uint64_t modifier;
void *priv;
} csi_img_s;
typedef struct csi_meta {
csi_meta_type_e type;
size_t size;
void *data;
} csi_meta_s;
typedef struct csi_frame {
csi_img_s img;
csi_meta_s meta;
} csi_frame_s;
int csi_frame_reference(csi_frame_s *frame_dest, csi_frame_s *frame_src);
int csi_frame_release(csi_frame_s *frame);
void *csi_frame_mmap(csi_frame_s *frame);
int csi_frame_munmap(csi_frame_s *frame);
#endif /* __CSI_FRAME_H__ */

176
include/hal/csi_frame_ex.h Normal file
View File

@@ -0,0 +1,176 @@
/**
* Copyright (C) 2021 Alibaba Group Holding Limited
**/
#ifndef _CSI_FRAME_EX_H
#define _CSI_FRAME_EX_H
#include <csi_common.h>
#define MAX_PLANE_COUNT 3
typedef enum {
CSI_PIXEL_FORMAT_RGB_444 = 0,
CSI_PIXEL_FORMAT_RGB_555,
CSI_PIXEL_FORMAT_RGB_565,
CSI_PIXEL_FORMAT_RGB_888,
CSI_PIXEL_FORMAT_BGR_444,
CSI_PIXEL_FORMAT_BGR_555,
CSI_PIXEL_FORMAT_BGR_565,
CSI_PIXEL_FORMAT_BGR_888,
CSI_PIXEL_FORMAT_ARGB_1555,
CSI_PIXEL_FORMAT_ARGB_4444,
CSI_PIXEL_FORMAT_ARGB_8565,
CSI_PIXEL_FORMAT_ARGB_8888,
CSI_PIXEL_FORMAT_ARGB_2BPP,
CSI_PIXEL_FORMAT_ABGR_1555,
CSI_PIXEL_FORMAT_ABGR_4444,
CSI_PIXEL_FORMAT_ABGR_8565,
CSI_PIXEL_FORMAT_ABGR_8888,
CSI_PIXEL_FORMAT_RGB_BAYER_8BPP,
CSI_PIXEL_FORMAT_RGB_BAYER_10BPP,
CSI_PIXEL_FORMAT_RGB_BAYER_12BPP,
CSI_PIXEL_FORMAT_RGB_BAYER_14BPP,
CSI_PIXEL_FORMAT_RGB_BAYER_16BPP,
CSI_PIXEL_FORMAT_YVU_PLANAR_422,
CSI_PIXEL_FORMAT_YVU_PLANAR_420,
CSI_PIXEL_FORMAT_YVU_PLANAR_444,
CSI_PIXEL_FORMAT_YVU_SEMIPLANAR_422,
CSI_PIXEL_FORMAT_YVU_SEMIPLANAR_420,
CSI_PIXEL_FORMAT_YVU_SEMIPLANAR_444,
CSI_PIXEL_FORMAT_YUV_SEMIPLANAR_422,
CSI_PIXEL_FORMAT_YUV_SEMIPLANAR_420,
CSI_PIXEL_FORMAT_YUV_SEMIPLANAR_444,
CSI_PIXEL_FORMAT_YUYV_PACKAGE_422,
CSI_PIXEL_FORMAT_YVYU_PACKAGE_422,
CSI_PIXEL_FORMAT_UYVY_PACKAGE_422,
CSI_PIXEL_FORMAT_VYUY_PACKAGE_422,
CSI_PIXEL_FORMAT_YYUV_PACKAGE_422,
CSI_PIXEL_FORMAT_YYVU_PACKAGE_422,
CSI_PIXEL_FORMAT_UVYY_PACKAGE_422,
CSI_PIXEL_FORMAT_VUYY_PACKAGE_422,
CSI_PIXEL_FORMAT_VY1UY0_PACKAGE_422,
CSI_PIXEL_FORMAT_YUV_400,
CSI_PIXEL_FORMAT_UV_420,
CSI_PIXEL_FORMAT_MAX
} csi_pixel_format_e;
#if 0
typedef enum {
CSI_PICTURE_TYPE_NONE = 0, /* undefined */
CSI_PICTURE_TYPE_I, /* intra */
CSI_PICTURE_TYPE_P, /* predicted */
CSI_PICTURE_TYPE_B, /* BI-dir predictd */
CSI_PICTURE_TYPE_S, /* S(GMC)-VOP MPEG-4 */
CSI_PICTURE_TYPE_SI, /* Switching intra */
CSI_PICTURE_TYPE_SP, /* Switching Predicted */
CSI_PICTURE_TYPE_BI, /* BI Type */
} csi_picture_type_e;
#endif
typedef enum {
CSI_CHROMA_LOCATION_LEFT,
CSI_CHROMA_LOCATION_CENTER,
CSI_CHROMA_LOCATION_TOPLEFT,
CSI_CHROMA_LOCATION_TOP,
CSI_CHROMA_LOCATION_BOTTOMLEFT,
CSI_CHROMA_LOCATION_BOTTOM,
CSI_CHROMA_LOCATION_DV420
} csi_chroma_location_e;
#if 0
typedef enum {
CSI_FRAME_COMPRESS_MODE_NONE = 0, /* no compress */
CSI_FRAME_COMPRESS_MODE_SEQ, /* compress unit is 256x1 bytes as a segment. */
CSI_FRAME_COMPRESS_MODE_TILE, /* compress unit is a tile. */
CSI_FRAME_COMPRESS_MODE_LINE, /* compress unit is the whole line. raw for VI */
CSI_FRAME_COMPRESS_MODE_FRAME, /* compress unit is the whole frame. YUV for VI(3DNR), RGB for TDE(write)/VO(read) */
CSI_FRAME_COMPRESS_MAX
} csi_frame_compress_mode;
#endif
typedef enum {
CSI_COLORSPACE_ACES, /* RGB color space ACES standardized as SMPTE ST 2065-1:2012. */
CSI_COLORSPACE_ACESCG, /* RGB color space ACEScg standardized as Academy S-2014-004. */
CSI_COLORSPACE_RGB, /* RGB color space Adobe RGB (1998). */
CSI_COLORSPACE_BT2020, /* RGB color space BT.2020 standardized as Rec. */
CSI_COLORSPACE_BT709, /* RGB color space BT.709 standardized as Rec. */
CSI_COLORSPACE_CIE_LAB, /* Lab color space CIE L*a*b*. */
CSI_COLORSPACE_CIE_XYZ, /* XYZ color space CIE XYZ. */
CSI_COLORSPACE_DCI_P3, /* RGB color space DCI-P3 standardized as SMPTE RP 431-2-2007. */
CSI_COLORSPACE_DISPLAY_p3, /* RGB color space Display P3 based on SMPTE RP 431-2-2007 and IEC 61966-2.1:1999. */
CSI_COLORSPACE_EXTENDED_SRGB, /* RGB color space scRGB-nl standardized as IEC 61966-2-2:2003. */
CSI_COLORSPACE_LINEAR_EXTENDED_SRGB, /* RGB color space scRGB standardized as IEC 61966-2-2:2003. */
CSI_COLORSPACE_LINEAR_SRGB, /* RGB color space sRGB standardized as IEC 61966-2.1:1999. */
CSI_COLORSPACE_NTSC_1953, /* RGB color space NTSC, 1953 standard. */
CSI_COLORSPACE_PRO_PHOTO_RGB, /* RGB color space NTSC, 1953 standard. */
CSI_COLORSPACE_SMPTE_C, /* RGB color space SMPTE C. */
CSI_COLORSPACE_SRGB /* RGB color space sRGB standardized as IEC 61966-2.1:1999. */
} csi_color_space_e;
typedef enum {
CSI_VIDEO_FORMAT_UNDEFINED,
CSI_VIDEO_FORMAT_COMPONENT,
CSI_VIDEO_FORMAT_PAL,
CSI_VIDEO_FORMAT_NTSC,
CSI_VIDEO_FORMAT_SECAM,
CSI_VIDEO_FORMAT_MAC
} csi_video_format_e;
typedef struct csi_frame_info {
int32_t width;
int32_t height;
/* the region of interest of the frame */
//csi_rect_s roi;
csi_pixel_format_e pixel_format;
//csi_frame_compress_mode compress_mode;
csi_color_space_e color_space;
csi_chroma_location_e chroma_location;
} csi_frame_info_s;
typedef struct csi_frame_data {
int64_t pts;
int64_t dts;
int64_t frame_num;
int8_t is_key_frame;
int8_t is_eos; /* last frame */
int32_t offset[MAX_PLANE_COUNT];
int32_t stride[MAX_PLANE_COUNT];
int32_t num_plane;
void *vir_addr[MAX_PLANE_COUNT];
union {
int fd[MAX_PLANE_COUNT]; /* -1 means invalid */
int64_t phy_addr[MAX_PLANE_COUNT]; /* 0 means invalid */
};
} csi_frame_data_s;
typedef struct csi_frame_ex {
csi_frame_info_s frame_info;
csi_frame_data_s frame_data;
void *opaque; /* not for user, DO NOT use or modify it */
} csi_frame_ex_s;
#if 0
typedef struct csi_bitstream {
void *buf;
uint32_t len;
uint8_t is_eos; //is the end of stream
uint8_t is_frame; //is whole compress frame data
} csi_bitstream_s;
#endif
#endif

204
include/hal/csi_g2d.h Normal file
View File

@@ -0,0 +1,204 @@
#ifndef __CSI_G2D_H__
#define __CSI_G2D_H__
#include <csi_g2d_types.h>
#ifdef __cplusplus
extern "C" {
#endif
struct _g2d_surface;
typedef struct _g2d_surface g2d_surface;
struct _g2d_context;
typedef struct _g2d_context g2d_context;
typedef enum _csi_g2d_tiling {
CSI_G2D_LINEAR,
} csi_g2d_tiling;
typedef enum _csi_g2d_rotation {
CSI_G2D_ROTATION_0_DEGREE,
CSI_G2D_ROTATION_90_DEGREE,
CSI_G2D_ROTATION_180_DEGREE,
CSI_G2D_ROTATION_270_DEGREE,
CSI_G2D_ROTATION_FLIP_X = 0x10000000,
CSI_G2D_ROTATION_FLIP_Y = 0x20000000,
} csi_g2d_rotation;
/* TODO: maximum 16 different modes */
typedef enum _csi_g2d_blend_mode {
CSI_G2D_BLEND_MODE_CLEAR,
CSI_G2D_BLEND_MODE_SRC,
CSI_G2D_BLEND_MODE_DST,
CSI_G2D_BLEND_MODE_SRC_OVER,
CSI_G2D_BLEND_MODE_DST_OVER,
CSI_G2D_BLEND_MODE_SRC_IN,
CSI_G2D_BLEND_MODE_DST_IN,
CSI_G2D_BLEND_MODE_SRC_OUT,
CSI_G2D_BLEND_MODE_DST_OUT,
CSI_G2D_BLEND_MODE_SRC_ATOP,
CSI_G2D_BLEND_MODE_DST_ATOP,
CSI_G2D_BLEND_MODE_ADD,
CSI_G2D_BLEND_MODE_XOR,
} csi_g2d_blend_mode;
typedef enum _csi_g2d_alpha_mode {
CSI_G2D_ALPHA_MODE_STRAIGHT,
CSI_G2D_ALPHA_MODE_INVERSED
} csi_g2d_alpha_mode;
typedef enum _csi_g2d_global_alpha_mode {
CSI_G2D_GLOBAL_ALPHA_MODE_OFF,
CSI_G2D_GLOBAL_ALPHA_MODE_ON,
CSI_G2D_GLOBAL_ALPHA_MODE_SCALE
} csi_g2d_global_alpha_mode;
typedef enum _csi_g2d_global_multiply_mode {
CSI_G2D_GLOBAL_COLOR_MULTIPLY_DISABLE,
CSI_G2D_GLOBAL_COLOR_MULTIPLY_ALPHA,
CSI_G2D_GLOBAL_COLOR_MULTIPLY_COLOR
} csi_g2d_global_multiply_mode;
typedef enum _csi_g2d_yuv_mode {
CSI_G2D_YUV_MODE_BT601,
CSI_G2D_YUV_MODE_BT709,
CSI_G2D_YUV_MODE_BT2020,
CSI_G2D_YUV_MODE_USER_DEFINED,
CSI_G2D_YUV_MODE_USER_DEFINED_CLAMP,
CSI_G2D_YUV_MODE_NUM,
} csi_g2d_yuv_mode;
typedef enum _csi_g2d_filter_tap {
CSI_G2D_FILTER_TAP_1,
CSI_G2D_FILTER_TAP_3,
CSI_G2D_FILTER_TAP_5
} csi_g2d_filter_tap;
typedef struct _csi_g2d_point {
int x;
int y;
} csi_g2d_point;
typedef struct _csi_g2d_line {
csi_g2d_point start;
csi_g2d_point end;
} csi_g2d_line;
typedef struct _csi_g2d_triangle {
csi_g2d_line line[3];
} csi_g2d_triangle;
typedef struct _csi_g2d_rectangle {
csi_g2d_line line[4];
} csi_g2d_rectangle;
typedef struct _csi_g2d_region {
unsigned int left;
unsigned int top;
unsigned int right;
unsigned int bottom;
} csi_g2d_region;
typedef struct _csi_g2d_surface {
g2d_surface *priv; /* point to g2d_surface */
int width; /* in pixels */
int height; /* in pixels */
int cpp[3]; /* bytes per pixel (per plane) */
int stride[3]; /* in bytes */
int nplanes; /* planes number */
int alignment; /* in pixels */
unsigned int format; /* in fourcc */
csi_g2d_tiling tiling;
void *lgcaddr[3];
unsigned int flags;
} csi_g2d_surface;
int csi_g2d_open(void);
int csi_g2d_close(void);
int csi_g2d_flush(void);
/* csi_g2d_surface APIs */
int csi_g2d_surface_create(csi_g2d_surface *csi_surface);
int csi_g2d_surface_destroy(csi_g2d_surface *csi_surface);
int csi_g2d_surface_select_source(unsigned int id);
int csi_g2d_surface_set_source(csi_g2d_surface *surface);
int csi_g2d_surface_set_target(csi_g2d_surface *surface);
int csi_g2d_surface_set_source_clipping(csi_g2d_region *region);
int csi_g2d_surface_set_target_clipping(csi_g2d_region *region);
int csi_g2d_surface_set_source_yuv_mode(csi_g2d_yuv_mode yuv_mode);
int csi_g2d_surface_set_target_yuv_mode(csi_g2d_yuv_mode yuv_mode);
int csi_g2d_surface_set_source_alpha_mode(
csi_g2d_alpha_mode alpha_mode,
csi_g2d_blend_mode blend_mode
);
int csi_g2d_surface_set_source_global_alpha_mode(
csi_g2d_global_alpha_mode global_mode,
unsigned int global_color
);
int csi_g2d_surface_set_source_multiply_mode(
bool multiply,
csi_g2d_global_multiply_mode global_mode
);
int csi_g2d_surface_set_target_alpha_mode(
csi_g2d_alpha_mode alpha_mode,
csi_g2d_blend_mode blend_mode
);
int csi_g2d_surface_set_target_global_alpha_mode(
csi_g2d_global_alpha_mode global_mode,
unsigned int global_color
);
int csi_g2d_surface_set_target_multiply_mode(
bool multiply,
bool demultiply
);
int csi_g2d_surface_enable_disable_alpha_blend(bool enable);
/* csi_g2d_brush APIs */
int csi_g2d_brush_create(unsigned int argb_color, bool convert);
int csi_g2d_brush_destroy(void);
int csi_g2d_palette_load(unsigned int *table,
unsigned int count,
bool convert);
/* csi_g2d_line APIs: draw line(s) in target */
int csi_g2d_line_draw_line(csi_g2d_line *lines, int nlines);
int csi_g2d_line_draw_triangle(csi_g2d_triangle *triangles,
int ntriangles);
int csi_g2d_line_draw_rectangle(csi_g2d_rectangle *rectangles,
int nrectangles);
/* blit properties config APIs */
int csi_g2d_blit_set_rotation(csi_g2d_rotation rotation);
int csi_g2d_blit_set_mirror(bool hmirror, bool vmirror);
int csi_g2d_blit_set_filter_tap(csi_g2d_filter_tap htap,
csi_g2d_filter_tap vtap);
/* clear target: clear color should be ARGB8888 */
int csi_g2d_fill(csi_g2d_region *regions,
int nregions,
unsigned int argb_color);
/* blit without resize, support alpha blending */
int csi_g2d_blit_bitblit(csi_g2d_region *target_regions, int nregions);
/* scaling up or down APIs */
int csi_g2d_blit_stretchblit(csi_g2d_region *target_regions, int nregions);
int csi_g2d_blit_filterblit(csi_g2d_region *target_regions, int nregions);
/* multisrc blit API */
int csi_g2d_blit_multisrc_blit(
unsigned int src_mask,
csi_g2d_region *target_regions,
int nregions
);
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More