mirror of
https://github.com/thead-yocto-mirror/csi_hal
synced 2026-06-21 08:52:22 +02:00
Linux_SDK_V0.9.5
This commit is contained in:
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal 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
54
Makefile
Normal 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
8
README.md
Normal 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
63
build.param
Normal 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
107
common_target.mk
Normal 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
52
examples/Makefile
Normal 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
5
examples/camera/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
camera_demo1
|
||||
camera_demo2
|
||||
camera_demo3
|
||||
camera_demo4
|
||||
camera_demo5
|
||||
85
examples/camera/Makefile
Normal file
85
examples/camera/Makefile
Normal 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
|
||||
678
examples/camera/cam_demo_ir.c
Normal file
678
examples/camera/cam_demo_ir.c
Normal 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__);
|
||||
}
|
||||
807
examples/camera/cam_demo_multi.c
Normal file
807
examples/camera/cam_demo_multi.c
Normal 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(¶ms[i]);
|
||||
break;
|
||||
case CAM_TYEP_IR:
|
||||
ctx[i]=camera_open(¶ms[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__);
|
||||
}
|
||||
710
examples/camera/cam_demo_simple.c
Normal file
710
examples/camera/cam_demo_simple.c
Normal 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__);
|
||||
}
|
||||
303
examples/camera/camera_demo1.c
Normal file
303
examples/camera/camera_demo1.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
357
examples/camera/camera_demo2.c
Normal file
357
examples/camera/camera_demo2.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
302
examples/camera/camera_demo3.c
Normal file
302
examples/camera/camera_demo3.c
Normal 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;
|
||||
}
|
||||
|
||||
11
examples/camera/camera_demo3.conf
Normal file
11
examples/camera/camera_demo3.conf
Normal 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|
|
||||
59
examples/camera/camera_demo3_srcs/app_dialogs.h
Normal file
59
examples/camera/camera_demo3_srcs/app_dialogs.h
Normal 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__ */
|
||||
17
examples/camera/camera_demo3_srcs/camera_ops.c
Normal file
17
examples/camera/camera_demo3_srcs/camera_ops.c
Normal 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"
|
||||
|
||||
18
examples/camera/camera_demo3_srcs/camera_ops.h
Normal file
18
examples/camera/camera_demo3_srcs/camera_ops.h
Normal 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__ */
|
||||
337
examples/camera/camera_demo3_srcs/checkbox.c
Normal file
337
examples/camera/camera_demo3_srcs/checkbox.c
Normal 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 */
|
||||
}
|
||||
355
examples/camera/camera_demo3_srcs/checklist.c
Normal file
355
examples/camera/camera_demo3_srcs/checklist.c
Normal 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 */
|
||||
}
|
||||
276
examples/camera/camera_demo3_srcs/dialog.h
Normal file
276
examples/camera/camera_demo3_srcs/dialog.h
Normal 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__ */
|
||||
|
||||
80
examples/camera/camera_demo3_srcs/dialog_camera_close.c
Normal file
80
examples/camera/camera_demo3_srcs/dialog_camera_close.c
Normal 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;
|
||||
}
|
||||
|
||||
90
examples/camera/camera_demo3_srcs/dialog_camera_list.c
Normal file
90
examples/camera/camera_demo3_srcs/dialog_camera_list.c
Normal 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;
|
||||
}
|
||||
|
||||
156
examples/camera/camera_demo3_srcs/dialog_camera_open.c
Normal file
156
examples/camera/camera_demo3_srcs/dialog_camera_open.c
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
418
examples/camera/camera_demo3_srcs/dialog_camera_property_list.c
Normal file
418
examples/camera/camera_demo3_srcs/dialog_camera_property_list.c
Normal 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;
|
||||
}
|
||||
|
||||
151
examples/camera/camera_demo3_srcs/dialog_camera_set_mode.c
Normal file
151
examples/camera/camera_demo3_srcs/dialog_camera_set_mode.c
Normal 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;
|
||||
}
|
||||
|
||||
90
examples/camera/camera_demo3_srcs/dialog_channel_list.c
Normal file
90
examples/camera/camera_demo3_srcs/dialog_channel_list.c
Normal 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);
|
||||
}
|
||||
|
||||
573
examples/camera/camera_demo3_srcs/dialog_channel_open.c
Normal file
573
examples/camera/camera_demo3_srcs/dialog_channel_open.c
Normal 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;
|
||||
}
|
||||
|
||||
339
examples/camera/camera_demo3_srcs/dialog_channel_run.c
Normal file
339
examples/camera/camera_demo3_srcs/dialog_channel_run.c
Normal 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;
|
||||
}
|
||||
|
||||
150
examples/camera/camera_demo3_srcs/dialog_channel_select.c
Normal file
150
examples/camera/camera_demo3_srcs/dialog_channel_select.c
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
302
examples/camera/camera_demo3_srcs/inputbox.c
Normal file
302
examples/camera/camera_demo3_srcs/inputbox.c
Normal 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 */
|
||||
}
|
||||
153
examples/camera/camera_demo3_srcs/menu_process.c
Normal file
153
examples/camera/camera_demo3_srcs/menu_process.c
Normal 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;
|
||||
}
|
||||
|
||||
30
examples/camera/camera_demo3_srcs/menu_process.h
Normal file
30
examples/camera/camera_demo3_srcs/menu_process.h
Normal 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);
|
||||
|
||||
442
examples/camera/camera_demo3_srcs/menubox.c
Normal file
442
examples/camera/camera_demo3_srcs/menubox.c
Normal 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 */
|
||||
}
|
||||
66
examples/camera/camera_demo3_srcs/param.c
Normal file
66
examples/camera/camera_demo3_srcs/param.c
Normal 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);
|
||||
}
|
||||
|
||||
42
examples/camera/camera_demo3_srcs/param.h
Normal file
42
examples/camera/camera_demo3_srcs/param.h
Normal 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__ */
|
||||
414
examples/camera/camera_demo3_srcs/textbox.c
Normal file
414
examples/camera/camera_demo3_srcs/textbox.c
Normal 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);
|
||||
}
|
||||
735
examples/camera/camera_demo3_srcs/util.c
Normal file
735
examples/camera/camera_demo3_srcs/util.c
Normal 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);
|
||||
}
|
||||
123
examples/camera/camera_demo3_srcs/yesno.c
Normal file
123
examples/camera/camera_demo3_srcs/yesno.c
Normal 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 */
|
||||
}
|
||||
297
examples/camera/camera_demo4.c
Normal file
297
examples/camera/camera_demo4.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
438
examples/camera/camera_frame_display.c
Normal file
438
examples/camera/camera_frame_display.c
Normal 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, ¶ms);
|
||||
VMEM_mmap(vmem, ¶ms);
|
||||
VMEM_export(vmem, ¶ms);
|
||||
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
391
examples/camera/camera_test1.c
Executable 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;
|
||||
}
|
||||
|
||||
41
examples/camera/opencv/Makefile
Normal file
41
examples/camera/opencv/Makefile
Normal 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
|
||||
24
examples/camera/opencv/apputilities.cpp
Normal file
24
examples/camera/opencv/apputilities.cpp
Normal 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;
|
||||
}
|
||||
|
||||
16
examples/camera/opencv/apputilities.h
Normal file
16
examples/camera/opencv/apputilities.h
Normal 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
|
||||
3
examples/camera/run_camera_demo3.sh
Executable file
3
examples/camera/run_camera_demo3.sh
Executable 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
1
examples/common/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
mtrace_demo
|
||||
27
examples/common/Makefile
Normal file
27
examples/common/Makefile
Normal 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
|
||||
25
examples/common/mtrace_demo.c
Normal file
25
examples/common/mtrace_demo.c
Normal 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");
|
||||
}
|
||||
|
||||
13
examples/common/run_mtrace_demo.sh
Executable file
13
examples/common/run_mtrace_demo.sh
Executable 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
3
examples/frame/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
frame_demo1
|
||||
frame_demo2
|
||||
consumer_dump_file.yuv
|
||||
33
examples/frame/Makefile
Normal file
33
examples/frame/Makefile
Normal 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
|
||||
109
examples/frame/frame_demo1.c
Normal file
109
examples/frame/frame_demo1.c
Normal 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;
|
||||
}
|
||||
|
||||
104
examples/frame/frame_demo2.c
Normal file
104
examples/frame/frame_demo2.c
Normal 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;
|
||||
}
|
||||
|
||||
187
examples/frame/frame_demo2_consumer.c
Normal file
187
examples/frame/frame_demo2_consumer.c
Normal 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;
|
||||
}
|
||||
|
||||
171
examples/frame/frame_demo2_producer.c
Normal file
171
examples/frame/frame_demo2_producer.c
Normal 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;
|
||||
}
|
||||
|
||||
214
examples/frame/frame_demo_common.c
Normal file
214
examples/frame/frame_demo_common.c
Normal 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");
|
||||
}
|
||||
|
||||
50
examples/frame/frame_demo_common.h
Normal file
50
examples/frame/frame_demo_common.h
Normal 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
1070
examples/g2d/g2d_demo.c
Normal file
File diff suppressed because it is too large
Load Diff
118
examples/resource/yuv420_1280x720_csky2016.yuv
Normal file
118
examples/resource/yuv420_1280x720_csky2016.yuv
Normal file
File diff suppressed because one or more lines are too long
3
examples/vdec/.gitignore
vendored
Normal file
3
examples/vdec/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
vdec_demo1
|
||||
vdec_demo2
|
||||
vdec_demo3
|
||||
30
examples/vdec/Makefile
Normal file
30
examples/vdec/Makefile
Normal 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
172
examples/vdec/vdec_demo1.c
Normal 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
1
examples/venc/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
venc_demo1
|
||||
30
examples/venc/Makefile
Normal file
30
examples/venc/Makefile
Normal 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
179
examples/venc/venc_demo1.c
Normal 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;
|
||||
}
|
||||
|
||||
42
include/common/camera_string.h
Normal file
42
include/common/camera_string.h
Normal 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
65
include/common/common.h
Normal 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__ */
|
||||
|
||||
58
include/common/common_datatype.h
Normal file
58
include/common/common_datatype.h
Normal 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__ */
|
||||
|
||||
34
include/common/common_errno.h
Normal file
34
include/common/common_errno.h
Normal 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__ */
|
||||
|
||||
20
include/common/dump_utils.h
Normal file
20
include/common/dump_utils.h
Normal 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__
|
||||
19
include/common/ipc_fd_transfer.h
Normal file
19
include/common/ipc_fd_transfer.h
Normal 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
154
include/common/list.h
Normal 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
50
include/common/llist.h
Normal 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
|
||||
|
||||
|
||||
104
include/common/producer_consumer_async.h
Normal file
104
include/common/producer_consumer_async.h
Normal 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__ */
|
||||
|
||||
47
include/common/ringbuffer.h
Normal file
47
include/common/ringbuffer.h
Normal 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
111
include/common/syslog.h
Normal 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
|
||||
50
include/hal/csi_allocator.h
Normal file
50
include/hal/csi_allocator.h
Normal 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
135
include/hal/csi_audio_ai.h
Normal 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
113
include/hal/csi_audio_ao.h
Normal 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
|
||||
168
include/hal/csi_audio_common.h
Normal file
168
include/hal/csi_audio_common.h
Normal 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
|
||||
61
include/hal/csi_audio_dec.h
Normal file
61
include/hal/csi_audio_dec.h
Normal 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
|
||||
63
include/hal/csi_audio_enc.h
Normal file
63
include/hal/csi_audio_enc.h
Normal 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
297
include/hal/csi_camera.h
Normal 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__ */
|
||||
62
include/hal/csi_camera_frame.h
Normal file
62
include/hal/csi_camera_frame.h
Normal 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__ */
|
||||
|
||||
62
include/hal/csi_camera_platform_spec.h
Normal file
62
include/hal/csi_camera_platform_spec.h
Normal 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__ */
|
||||
|
||||
93
include/hal/csi_camera_property.h
Normal file
93
include/hal/csi_camera_property.h
Normal 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
68
include/hal/csi_common.h
Normal 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
54
include/hal/csi_fce.h
Normal 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
94
include/hal/csi_fce_cfg.h
Normal 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
156
include/hal/csi_frame.h
Normal 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
176
include/hal/csi_frame_ex.h
Normal 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
204
include/hal/csi_g2d.h
Normal 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
Reference in New Issue
Block a user