2807 lines
99 KiB
C++
Raw Permalink Normal View History

2025-05-10 21:58:58 +08:00
/*
* V4L2 video capture example
* AUTHOT : Jacob Chen
* DATA : 2018-02-25
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <dlfcn.h>
#include <signal.h>
#include <dirent.h>
#if ISPDEMO_ENABLE_DRM
#include "drmDsp.h"
#endif
#include "uAPI2/rk_aiq_user_api2_sysctl.h"
#include "rk_aiq_user_api2_debug.h"
#include "sample_image_process.h"
#include "rkisp_demo.h"
#include <termios.h>
#include "ae_algo_demo/third_party_ae_algo.h"
//#include "awb_algo_demo/third_party_awb_algo.h" //for rk3588
#include "awb_algo_demo/third_party_awbV32_algo.h" //for rv1106
#include "af_algo_demo/third_party_af_algo.h"
#if ISPDEMO_ENABLE_RGA && ISPDEMO_ENABLE_DRM
#include "display.h"
#include "rga.h"
#endif
#include <list>
#include <vector>
#include <string>
#include <algorithm>
#define CLEAR(x) memset(&(x), 0, sizeof(x))
#define FMT_NUM_PLANES 1
#define BUFFER_COUNT 3
#ifdef ANDROID
#define CAPTURE_RAW_PATH "/data"
#define DEFAULT_CAPTURE_RAW_PATH "/data/capture_image"
#else
#define CAPTURE_RAW_PATH "/tmp"
#define DEFAULT_CAPTURE_RAW_PATH "/tmp/capture_image"
#endif
#define CAPTURE_CNT_FILENAME ".capture_cnt"
// #define ENABLE_UAPI_TEST
#define IQFILE_PATH_MAX_LEN 256
// #define CUSTOM_AE_DEMO_TEST
// #define CUSTOM_GROUP_AE_DEMO_TEST
//#define CUSTOM_AWB_DEMO_TEST
// #define TEST_MEMS_SENSOR_INTF
// #define CUSTOM_AF_DEMO_TEST
// #define CUSTOM_GROUP_AWB_DEMO_TEST
#ifdef ISPFEC_API
#include "IspFec/rk_ispfec_api.h"
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <libdrm/drm_mode.h>
#include <drm_fourcc.h>
struct drm_buf {
int fb_id;
uint32_t handle;
uint32_t size;
uint32_t pitch;
char *map;
int dmabuf_fd;
};
static rk_ispfec_ctx_t* g_ispfec_ctx = NULL;
static rk_ispfec_cfg_t g_ispfec_cfg;
struct drm_buf g_drm_buf_pic_out;
struct drm_buf g_drm_buf_xint;
struct drm_buf g_drm_buf_xfra;
struct drm_buf g_drm_buf_yint;
struct drm_buf g_drm_buf_yfra;
#endif
struct buffer {
void *start;
size_t length;
int export_fd;
int sequence;
};
enum TEST_CTL_TYPE {
TEST_CTL_TYPE_DEFAULT,
TEST_CTL_TYPE_REPEAT_INIT_PREPARE_START_STOP_DEINIT,
TEST_CTL_TYPE_REPEAT_START_STOP,
TEST_CTL_TYPE_REPEAT_PREPARE_START_STOP,
};
static struct termios oldt;
static int silent;
static demo_context_t *g_main_ctx = NULL, *g_second_ctx = NULL, *g_third_ctx = NULL, *g_fourth_ctx = NULL;
static bool _if_quit = false;
#ifdef ISPFEC_API
int alloc_drm_buffer(int fd, int width, int height,
int bpp, struct drm_buf *buf)
{
struct drm_mode_create_dumb alloc_arg;
struct drm_mode_map_dumb mmap_arg;
struct drm_mode_destroy_dumb destory_arg;
void *map;
int ret;
memset(&alloc_arg, 0, sizeof(alloc_arg));
alloc_arg.bpp = bpp;
alloc_arg.width = width;
alloc_arg.height = height;
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg);
if (ret) {
printf("failed to create dumb buffer\n");
return ret;
}
memset(&mmap_arg, 0, sizeof(mmap_arg));
mmap_arg.handle = alloc_arg.handle;
ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg);
if (ret) {
printf("failed to create map dumb\n");
ret = -EINVAL;
goto destory_dumb;
}
map = mmap(0, alloc_arg.size,
PROT_READ | PROT_WRITE, MAP_SHARED,
fd, mmap_arg.offset);
if (map == MAP_FAILED) {
printf("failed to mmap buffer\n");
ret = -EINVAL;
goto destory_dumb;
}
ret = drmPrimeHandleToFD(fd, alloc_arg.handle, 0,
&buf->dmabuf_fd);
if (ret) {
printf("failed to get dmabuf fd\n");
munmap(map, alloc_arg.size);
ret = -EINVAL;
goto destory_dumb;
}
buf->size = alloc_arg.size;
buf->map = (char*)map;
destory_dumb:
memset(&destory_arg, 0, sizeof(destory_arg));
destory_arg.handle = alloc_arg.handle;
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
return ret;
}
int free_drm_buffer(int fd, struct drm_buf *buf)
{
if (buf) {
close(buf->dmabuf_fd);
return munmap(buf->map, buf->size);
}
return -EINVAL;
}
int init_ispfec_bufs(rk_ispfec_cfg_t* cfg)
{
int ret = 0;
int drm_fd = drmOpen("rockchip", NULL);
if (drm_fd < 0) {
printf("failed to open rockchip drm\n");
return -1;
}
int mesh_size = rk_ispfec_api_calFecMeshsize(cfg->in_width, cfg->in_height);
printf("\nmesh_size:%d\n", mesh_size);
ret = alloc_drm_buffer(drm_fd, mesh_size * 2, 1, 8, &g_drm_buf_xint);
if (ret)
goto close_drm_fd;
printf("xint fd:%d size:%d\n", g_drm_buf_xint.dmabuf_fd, g_drm_buf_xint.size);
ret = alloc_drm_buffer(drm_fd, mesh_size, 1, 8, &g_drm_buf_xfra);
if (ret)
goto free_drm_buf_xint;
printf("xfra fd:%d size:%d\n", g_drm_buf_xfra.dmabuf_fd, g_drm_buf_xfra.size);
ret = alloc_drm_buffer(drm_fd, mesh_size * 2, 1, 8, &g_drm_buf_yint);
if (ret)
goto free_drm_buf_xfra;
printf("yint fd:%d size:%d\n", g_drm_buf_yint.dmabuf_fd, g_drm_buf_yint.size);
ret = alloc_drm_buffer(drm_fd, mesh_size, 1, 8, &g_drm_buf_yfra);
if (ret)
goto free_drm_buf_yint;
printf("yfra fd:%d size:%d\n", g_drm_buf_yfra.dmabuf_fd, g_drm_buf_yfra.size);
ret = alloc_drm_buffer(drm_fd, cfg->out_width, cfg->out_height * 3 / 2, 8, &g_drm_buf_pic_out);
if (ret)
goto free_drm_buf_yfra;
printf("out pic fd:%d size:%d\n", g_drm_buf_pic_out.dmabuf_fd, g_drm_buf_pic_out.size);
cfg->mesh_xint.dmaFd = g_drm_buf_xint.dmabuf_fd;
cfg->mesh_xint.size = g_drm_buf_xint.size;
cfg->mesh_xint.vir_addr = g_drm_buf_xint.map;
cfg->mesh_xfra.dmaFd = g_drm_buf_xfra.dmabuf_fd;
cfg->mesh_xfra.size = g_drm_buf_xfra.size;
cfg->mesh_xfra.vir_addr = g_drm_buf_xfra.map;
cfg->mesh_yint.dmaFd = g_drm_buf_yint.dmabuf_fd;
cfg->mesh_yint.size = g_drm_buf_yint.size;
cfg->mesh_yint.vir_addr = g_drm_buf_yint.map;
cfg->mesh_yfra.dmaFd = g_drm_buf_yfra.dmabuf_fd;
cfg->mesh_yfra.size = g_drm_buf_yfra.size;
cfg->mesh_yfra.vir_addr = g_drm_buf_yfra.map;
goto close_drm_fd;
free_drm_buf_pic_out:
free_drm_buffer(drm_fd, &g_drm_buf_pic_out);
free_drm_buf_yfra:
free_drm_buffer(drm_fd, &g_drm_buf_yfra);
free_drm_buf_yint:
free_drm_buffer(drm_fd, &g_drm_buf_yfra);
free_drm_buf_xfra:
free_drm_buffer(drm_fd, &g_drm_buf_xfra);
free_drm_buf_xint:
free_drm_buffer(drm_fd, &g_drm_buf_xint);
close_drm_fd:
close(drm_fd);
return ret;
}
void deinit_ispfec_bufs()
{
free_drm_buffer(-1, &g_drm_buf_pic_out);
free_drm_buffer(-1, &g_drm_buf_yfra);
free_drm_buffer(-1, &g_drm_buf_yfra);
free_drm_buffer(-1, &g_drm_buf_xfra);
free_drm_buffer(-1, &g_drm_buf_xint);
}
#endif
//restore terminal settings
void restore_terminal_settings(void)
{
// Apply saved settings
tcsetattr(0, TCSANOW, &oldt);
}
//make terminal read 1 char at a time
void disable_terminal_return(void)
{
struct termios newt;
//save terminal settings
tcgetattr(0, &oldt);
//init new settings
newt = oldt;
//change settings
newt.c_lflag &= ~(ICANON | ECHO);
//apply settings
tcsetattr(0, TCSANOW, &newt);
//make sure settings will be restored when program ends
atexit(restore_terminal_settings);
}
char* get_dev_name(demo_context_t* ctx)
{
if (ctx->dev_using == 1)
return ctx->dev_name;
else if (ctx->dev_using == 2)
return ctx->dev_name2;
else if (ctx->dev_using == 3)
return ctx->dev_name3;
else if (ctx->dev_using == 4)
return ctx->dev_name4;
else {
ERR("!!!dev_using is not supported!!!");
return NULL;
}
}
char* get_sensor_name(demo_context_t* ctx)
{
return ctx->sns_name;
}
void test_update_iqfile(const demo_context_t* demo_ctx)
{
char iqfile[IQFILE_PATH_MAX_LEN] = {0};
printf("\nspecial an new iqfile:\n");
strcat(iqfile, demo_ctx->iqpath);
strcat(iqfile, "/");
char* ret = fgets(iqfile + strlen(iqfile), IQFILE_PATH_MAX_LEN, stdin);
char* json = strstr(iqfile, "json");
if (!json) {
printf("[AIQ]input is not an valide json:%s\n", iqfile);
return;
}
/* fgets may add '\n' in the end of input, delete it */
json += strlen("json");
*json = '\0';
printf("[AIQ] appling new iq file:%s\n", iqfile);
rk_aiq_uapi2_sysctl_updateIq(demo_ctx->aiq_ctx, iqfile);
}
#if 0
static int set_ae_onoff(const rk_aiq_sys_ctx_t* ctx, bool onoff);
void test_imgproc(const demo_context_t* demo_ctx) {
if (demo_ctx == NULL) {
return;
}
const rk_aiq_sys_ctx_t* ctx = (const rk_aiq_sys_ctx_t*)(demo_ctx->aiq_ctx);
/*TODO: when rkaiq_3A_server & rkisp_demo run in two different shell, rk_aiq_sys_ctx_t would be null?*/
if (ctx == NULL) {
printf("ERROR : rk_aiq_sys_ctx_t is null.\n");
_if_quit = true;
return;
}
int key = getchar();
printf("press key=[%c]\n", key);
opMode_t mode;
paRange_t range;
expPwrLineFreq_t freq;
rk_aiq_wb_scene_t scene;
rk_aiq_wb_gain_t gain;
rk_aiq_wb_cct_t ct;
antiFlickerMode_t flicker;
switch (key)
{
case '0':
rk_aiq_uapi_setExpMode(ctx, OP_MANUAL);
printf("set exp manual\n");
break;
case '.':
rk_aiq_uapi_setExpMode(ctx, OP_AUTO);
printf("set exp auto\n");
break;
case '1':
rk_aiq_uapi_getExpMode(ctx, &mode);
printf("exp mode=%d\n", mode);
break;
case '2':
range.min = 5.0f;
range.max = 8.0f;
rk_aiq_uapi_setExpGainRange(ctx, &range);
printf("set gain range\n");
break;
case '3':
rk_aiq_uapi_getExpGainRange(ctx, &range);
printf("get gain range[%f,%f]\n", range.min, range.max);
break;
case '4':
range.min = 10.0f;
range.max = 30.0f;
rk_aiq_uapi_setExpTimeRange(ctx, &range);
printf("set time range\n");
break;
case '5':
rk_aiq_uapi_getExpTimeRange(ctx, &range);
printf("get time range[%f,%f]\n", range.min, range.max);
break;
case '6':
rk_aiq_uapi_setExpPwrLineFreqMode(ctx, EXP_PWR_LINE_FREQ_50HZ);
printf("setExpPwrLineFreqMode 50hz\n");
break;
case ',':
rk_aiq_uapi_setExpPwrLineFreqMode(ctx, EXP_PWR_LINE_FREQ_60HZ);
printf("setExpPwrLineFreqMode 60hz\n");
break;
case '7':
rk_aiq_uapi_getExpPwrLineFreqMode(ctx, &freq);
printf("getExpPwrLineFreqMode=%d\n", freq);
break;
case '8':
rk_aiq_uapi_setWBMode(ctx, OP_MANUAL);
printf("setWBMode manual\n");
break;
case '/':
rk_aiq_uapi_setWBMode(ctx, OP_AUTO);
printf("setWBMode auto\n");
break;
case '9':
rk_aiq_uapi_getWBMode(ctx, &mode);
printf("getWBMode=%d\n", mode);
break;
case 'a':
rk_aiq_uapi_lockAWB(ctx);
printf("lockAWB\n");
break;
case 'b':
rk_aiq_uapi_unlockAWB(ctx);
printf("unlockAWB\n");
break;
case 'c':
rk_aiq_uapi_setMWBScene(ctx, RK_AIQ_WBCT_TWILIGHT);
printf("setMWBScene\n");
break;
case 'd':
rk_aiq_uapi_getMWBScene(ctx, &scene);
printf("getMWBScene=%d\n", scene);
break;
case 'e':
gain.rgain = 0.5f;
gain.grgain = 0.5f;
gain.gbgain = 0.5f;
gain.bgain = 0.5f;
rk_aiq_uapi_setMWBGain(ctx, &gain);
printf("setMWBGain\n");
break;
case 'f':
rk_aiq_uapi_getMWBGain(ctx, &gain);
printf("getMWBGain=[%f %f %f %f]\n", gain.rgain, gain.grgain, gain.gbgain, gain.bgain);
break;
case 'g':
break;
case 'h':
break;
case 'i':
rk_aiq_uapi_setAntiFlickerMode(ctx, ANTIFLICKER_NORMAL_MODE);
printf("setAntiFlickerMode normal\n");
break;
case 'j':
rk_aiq_uapi_setAntiFlickerMode(ctx, ANTIFLICKER_AUTO_MODE);
printf("setAntiFlickerMode auto\n");
break;
case 'k':
rk_aiq_uapi_getAntiFlickerMode(ctx, &flicker);
printf("getAntiFlickerMode=%d\n", flicker);
break;
case 'l':
rk_aiq_uapi_setSaturation(ctx, 50);
printf("setSaturation\n");
break;
case 'm':
unsigned int level1;
rk_aiq_uapi_getSaturation(ctx, &level1);
printf("getSaturation=%d\n", level1);
break;
case 'n':
rk_aiq_uapi_setCrSuppsn(ctx, 50);
printf("setCrSuppsn\n");
break;
case 'o':
unsigned int level2;
rk_aiq_uapi_getCrSuppsn(ctx, &level2);
printf("getCrSuppsn=%d\n", level2);
break;
case 'p':
//rk_aiq_uapi_setHDRMode(ctx, OP_AUTO);
printf("setHDRMode\n");
break;
case 'q':
//rk_aiq_uapi_setHDRMode(ctx, OP_MANUAL);
printf("setHDRMode\n");
break;
case 'r':
//rk_aiq_uapi_getHDRMode(ctx, &mode);
printf("getHDRMode=%d\n", mode);
break;
case 's': {
unsigned int set_anr_strength = 80;
unsigned int get_anr_strength = 0;
rk_aiq_uapi_setANRStrth(ctx, set_anr_strength);
printf("setANRStrth %u \n", set_anr_strength);
sleep(1);
rk_aiq_uapi_getANRStrth(ctx, &get_anr_strength);
printf("getANRStrth %u \n", get_anr_strength);
break;
}
case 't': {
unsigned int set_strength = 80;
unsigned int get_space_strength = 0;
unsigned int get_mfnr_strength = 0;
bool state;
rk_aiq_uapi_setMSpaNRStrth(ctx, true, set_strength);
rk_aiq_uapi_setMTNRStrth(ctx, true, set_strength);
printf("setMSpaNRStrth and setMTNRStrth :%u \n", set_strength);
rk_aiq_uapi_getMSpaNRStrth(ctx, &state, &get_space_strength);
rk_aiq_uapi_getMTNRStrth(ctx, &state, &get_mfnr_strength);
printf("setMSpaNRStrth and setMTNRStrth :%u %u\n", get_space_strength, get_mfnr_strength);
break;
}
case 'u':
//rk_aiq_uapi_setDhzMode(ctx, OP_MANUAL);
//printf("setDhzMode\n");
break;
case 'v':
//rk_aiq_uapi_getDhzMode(ctx, &mode);
// printf("getDhzMode=%d\n", mode);
break;
case 'w':
{
bool stat = false;
//unsigned int level4 = 0;
//rk_aiq_uapi_getMHDRStrth(ctx, &stat, &level4);
//printf("getMHDRStrth: status:%d, level=%d\n", stat, level4);
}
break;
case 'x':
//rk_aiq_uapi_setMHDRStrth(ctx, true, 8);
//printf("setMHDRStrth true\n");
break;
case 'y':
{
bool mod_en;
rk_aiq_uapi2_sysctl_getModuleCtl(ctx, RK_MODULE_TNR, &mod_en);
printf("getModuleCtl=%d\n", mod_en);
if (mod_en) {
rk_aiq_uapi2_sysctl_setModuleCtl(ctx, RK_MODULE_TNR, false);
} else {
rk_aiq_uapi2_sysctl_setModuleCtl(ctx, RK_MODULE_TNR, true);
}
}
break;
case 'z':
rk_aiq_uapi_setFocusMode(ctx, OP_AUTO);
printf("setFocusMode OP_AUTO\n");
break;
case 'A':
rk_aiq_uapi_setFocusMode(ctx, OP_SEMI_AUTO);
printf("setFocusMode OP_SEMI_AUTO\n");
break;
case 'B':
rk_aiq_uapi_setFocusMode(ctx, OP_MANUAL);
printf("setFocusMode OP_MANUAL\n");
break;
case 'C':
rk_aiq_uapi_manualTrigerFocus(ctx);
printf("manualTrigerFocus\n");
break;
case 'D': {
rk_aiq_af_zoomrange range;
int code;
rk_aiq_uapi_getZoomRange(ctx, &range);
printf("zoom.min_pos %d, zoom.max_pos %d\n", range.min_pos, range.max_pos);
rk_aiq_uapi_getOpZoomPosition(ctx, &code);
printf("getOpZoomPosition code %d\n", code);
code += 20;
if (code > range.max_pos)
code = range.max_pos;
rk_aiq_uapi_setOpZoomPosition(ctx, code);
rk_aiq_uapi_endOpZoomChange(ctx);
printf("setOpZoomPosition %d\n", code);
}
break;
case 'E': {
rk_aiq_af_zoomrange range;
int code;
rk_aiq_uapi_getZoomRange(ctx, &range);
printf("zoom.min_pos %d, zoom.max_pos %d\n", range.min_pos, range.max_pos);
rk_aiq_uapi_getOpZoomPosition(ctx, &code);
printf("getOpZoomPosition code %d\n", code);
code -= 20;
if (code < range.min_pos)
code = range.min_pos;
rk_aiq_uapi_setOpZoomPosition(ctx, code);
rk_aiq_uapi_endOpZoomChange(ctx);
printf("setOpZoomPosition %d\n", code);
}
break;
case 'F': {
rk_aiq_af_focusrange range;
short code;
rk_aiq_uapi_getFocusRange(ctx, &range);
printf("focus.min_pos %d, focus.max_pos %d\n", range.min_pos, range.max_pos);
rk_aiq_uapi_getFixedModeCode(ctx, &code);
code++;
if (code > range.max_pos)
code = range.max_pos;
rk_aiq_uapi_setFixedModeCode(ctx, code);
printf("setFixedModeCode %d\n", code);
}
break;
case 'G': {
rk_aiq_af_focusrange range;
short code;
rk_aiq_uapi_getFocusRange(ctx, &range);
printf("focus.min_pos %d, focus.max_pos %d\n", range.min_pos, range.max_pos);
rk_aiq_uapi_getFixedModeCode(ctx, &code);
code--;
if (code < range.min_pos)
code = range.min_pos;
rk_aiq_uapi_setFixedModeCode(ctx, code);
printf("setFixedModeCode %d\n", code);
}
break;
case 'H': {
rk_aiq_af_attrib_t attr;
uint16_t gamma_y[RKAIQ_RAWAF_GAMMA_NUM] =
{0, 45, 108, 179, 245, 344, 409, 459, 500, 567, 622, 676, 759, 833, 896, 962, 1023};
rk_aiq_user_api_af_GetAttrib(ctx, &attr);
attr.manual_meascfg.contrast_af_en = 1;
attr.manual_meascfg.rawaf_sel = 0; // normal = 0; hdr = 1
attr.manual_meascfg.window_num = 2;
attr.manual_meascfg.wina_h_offs = 2;
attr.manual_meascfg.wina_v_offs = 2;
attr.manual_meascfg.wina_h_size = 2580;
attr.manual_meascfg.wina_v_size = 1935;
attr.manual_meascfg.winb_h_offs = 500;
attr.manual_meascfg.winb_v_offs = 600;
attr.manual_meascfg.winb_h_size = 300;
attr.manual_meascfg.winb_v_size = 300;
attr.manual_meascfg.gamma_flt_en = 1;
memcpy(attr.manual_meascfg.gamma_y, gamma_y, RKAIQ_RAWAF_GAMMA_NUM * sizeof(uint16_t));
attr.manual_meascfg.gaus_flt_en = 1;
attr.manual_meascfg.gaus_h0 = 0x20;
attr.manual_meascfg.gaus_h1 = 0x10;
attr.manual_meascfg.gaus_h2 = 0x08;
attr.manual_meascfg.afm_thres = 4;
attr.manual_meascfg.lum_var_shift[0] = 0;
attr.manual_meascfg.afm_var_shift[0] = 0;
attr.manual_meascfg.lum_var_shift[1] = 4;
attr.manual_meascfg.afm_var_shift[1] = 4;
attr.manual_meascfg.sp_meas.enable = true;
attr.manual_meascfg.sp_meas.ldg_xl = 10;
attr.manual_meascfg.sp_meas.ldg_yl = 28;
attr.manual_meascfg.sp_meas.ldg_kl = (255 - 28) * 256 / 45;
attr.manual_meascfg.sp_meas.ldg_xh = 118;
attr.manual_meascfg.sp_meas.ldg_yh = 8;
attr.manual_meascfg.sp_meas.ldg_kh = (255 - 8) * 256 / 15;
attr.manual_meascfg.sp_meas.highlight_th = 245;
attr.manual_meascfg.sp_meas.highlight2_th = 200;
rk_aiq_user_api_af_SetAttrib(ctx, &attr);
}
break;
case 'I':
if (CHECK_ISP_HW_V20()) {
rk_aiq_nr_IQPara_t stNRIQPara;
rk_aiq_nr_IQPara_t stGetNRIQPara;
stNRIQPara.module_bits = (1 << ANR_MODULE_BAYERNR) | (1 << ANR_MODULE_MFNR) | (1 << ANR_MODULE_UVNR) | (1 << ANR_MODULE_YNR);
stGetNRIQPara.module_bits = (1 << ANR_MODULE_BAYERNR) | (1 << ANR_MODULE_MFNR) | (1 << ANR_MODULE_UVNR) | (1 << ANR_MODULE_YNR);
rk_aiq_user_api_anr_GetIQPara(ctx, &stNRIQPara);
for(int m = 0; m < 3; m++) {
for(int k = 0; k < 2; k++) {
for(int i = 0; i < CALIBDB_NR_SHARP_MAX_ISO_LEVEL; i++ ) {
//bayernr
stNRIQPara.stBayernrPara.mode_cell[m].setting[k].filtPara[i] = 0.1;
stNRIQPara.stBayernrPara.mode_cell[m].setting[k].lamda = 500;
stNRIQPara.stBayernrPara.mode_cell[m].setting[k].fixW[0][i] = 0.1;
stNRIQPara.stBayernrPara.mode_cell[m].setting[k].fixW[1][i] = 0.1;
stNRIQPara.stBayernrPara.mode_cell[m].setting[k].fixW[2][i] = 0.1;
stNRIQPara.stBayernrPara.mode_cell[m].setting[k].fixW[3][i] = 0.1;
//mfnr
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_y[0] = 2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_y[1] = 2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_y[2] = 2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_y[3] = 2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_uv[0] = 2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_uv[1] = 2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_uv[2] = 2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_lo_bfscale[0] = 0.4;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_lo_bfscale[1] = 0.6;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_lo_bfscale[2] = 0.8;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_lo_bfscale[3] = 1.0;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_hi_bfscale[0] = 0.4;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_hi_bfscale[1] = 0.6;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_hi_bfscale[2] = 0.8;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_hi_bfscale[3] = 1.0;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_lo_bfscale[0] = 0.1;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_lo_bfscale[1] = 0.2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_lo_bfscale[2] = 0.3;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_hi_bfscale[0] = 0.1;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_hi_bfscale[1] = 0.2;
stNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_hi_bfscale[2] = 0.3;
//ynr
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].lo_bfScale[0] = 0.4;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].lo_bfScale[1] = 0.6;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].lo_bfScale[2] = 0.8;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].lo_bfScale[3] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_bfScale[0] = 0.4;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_bfScale[1] = 0.6;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_bfScale[2] = 0.8;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_bfScale[3] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseStrength = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseWeight[0] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseWeight[1] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseWeight[2] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseWeight[3] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].denoise_weight[0] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].denoise_weight[1] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].denoise_weight[2] = 1.0;
stNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].denoise_weight[3] = 1.0;
//uvnr
stNRIQPara.stUvnrPara.mode_cell[m].setting[k].step0_uvgrad_ratio[i] = 100;
stNRIQPara.stUvnrPara.mode_cell[m].setting[k].step1_median_ratio[i] = 0.5;
stNRIQPara.stUvnrPara.mode_cell[m].setting[k].step2_median_ratio[i] = 0.5;
stNRIQPara.stUvnrPara.mode_cell[m].setting[k].step1_bf_sigmaR[i] = 20;
stNRIQPara.stUvnrPara.mode_cell[m].setting[k].step2_bf_sigmaR[i] = 16;
stNRIQPara.stUvnrPara.mode_cell[m].setting[k].step3_bf_sigmaR[i] = 8;
}
}
}
rk_aiq_user_api_anr_SetIQPara(ctx, &stNRIQPara);
sleep(5);
//printf all the para
rk_aiq_user_api_anr_GetIQPara(ctx, &stGetNRIQPara);
for(int m = 0; m < 1; m++) {
for(int k = 0; k < 1; k++) {
for(int i = 0; i < CALIBDB_NR_SHARP_MAX_ISO_LEVEL; i++ ) {
printf("\n\n!!!!!!!!!!set:%d cell:%d !!!!!!!!!!\n", k, i);
printf("oyyf222 bayernr: fiter:%f lamda:%f fixw:%f %f %f %f\n",
stGetNRIQPara.stBayernrPara.mode_cell[m].setting[k].filtPara[i],
stGetNRIQPara.stBayernrPara.mode_cell[m].setting[k].lamda,
stGetNRIQPara.stBayernrPara.mode_cell[m].setting[k].fixW[0][i],
stGetNRIQPara.stBayernrPara.mode_cell[m].setting[k].fixW[1][i],
stGetNRIQPara.stBayernrPara.mode_cell[m].setting[k].fixW[2][i],
stGetNRIQPara.stBayernrPara.mode_cell[m].setting[k].fixW[3][i]);
printf("oyyf222 mfnr: limiy:%f %f %f %f uv: %f %f %f, y_lo:%f %f %f %f y_hi:%f %f %f %f uv_lo:%f %f %f uv_hi:%f %f %f\n",
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_y[0],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_y[1],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_y[2],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_y[3],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_uv[0],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_uv[1],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].weight_limit_uv[2],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_lo_bfscale[0],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_lo_bfscale[1],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_lo_bfscale[2],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_lo_bfscale[3],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_hi_bfscale[0],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_hi_bfscale[1],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_hi_bfscale[2],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].y_hi_bfscale[3],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_lo_bfscale[0],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_lo_bfscale[1],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_lo_bfscale[2],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_hi_bfscale[0],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_hi_bfscale[1],
stGetNRIQPara.stMfnrPara.mode_cell[m].setting[k].mfnr_iso[i].uv_hi_bfscale[2]);
printf("oyyf222 ynr: lo_bf:%f %f %f %f lo_do:%f %f %f %f hi_bf:%f %f %f %f stre:%f hi_do:%f %f %f %f\n",
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].lo_bfScale[0],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].lo_bfScale[1],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].lo_bfScale[2],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].lo_bfScale[3],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].denoise_weight[0],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].denoise_weight[1],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].denoise_weight[2],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].denoise_weight[3],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_bfScale[0],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_bfScale[1],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_bfScale[2],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_bfScale[3],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseStrength,
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseWeight[0],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseWeight[1],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseWeight[2],
stGetNRIQPara.stYnrPara.mode_cell[m].setting[k].ynr_iso[i].hi_denoiseWeight[3]
);
printf("oyyf222 uvnr: uv:%f med:%f %f sigmaR:%f %f %f\n",
stGetNRIQPara.stUvnrPara.mode_cell[m].setting[k].step0_uvgrad_ratio[i],
stGetNRIQPara.stUvnrPara.mode_cell[m].setting[k].step1_median_ratio[i],
stGetNRIQPara.stUvnrPara.mode_cell[m].setting[k].step2_median_ratio[i],
stGetNRIQPara.stUvnrPara.mode_cell[m].setting[k].step1_bf_sigmaR[i],
stGetNRIQPara.stUvnrPara.mode_cell[m].setting[k].step2_bf_sigmaR[i],
stGetNRIQPara.stUvnrPara.mode_cell[m].setting[k].step3_bf_sigmaR[i]);
printf("!!!!!!!!!!set:%d cell:%d end !!!!!!!!!!\n\n", k, i);
}
}
}
}
break;
case 'J':
if (CHECK_ISP_HW_V20()) {
rk_aiq_sharp_IQpara_t stSharpIQpara;
rk_aiq_sharp_IQpara_t stGetSharpIQpara;
stSharpIQpara.module_bits = (1 << ASHARP_MODULE_SHARP) | (1 << ASHARP_MODULE_EDGEFILTER) ;
rk_aiq_user_api_asharp_GetIQPara(ctx, &stSharpIQpara);
for(int m = 0; m < 3; m++) {
for(int k = 0; k < 2; k++) {
for(int i = 0; i < CALIBDB_NR_SHARP_MAX_ISO_LEVEL; i++ ) {
stSharpIQpara.stSharpPara.mode_cell[m].setting[k].sharp_iso[i].hratio = 1.9;
stSharpIQpara.stSharpPara.mode_cell[m].setting[k].sharp_iso[i].lratio = 0.4;
stSharpIQpara.stSharpPara.mode_cell[m].setting[k].sharp_iso[i].mf_sharp_ratio = 5.0;
stSharpIQpara.stSharpPara.mode_cell[m].setting[k].sharp_iso[i].hf_sharp_ratio = 6.0;
stSharpIQpara.stEdgeFltPara.mode_cell[m].setting[k].edgeFilter_iso[i].edge_thed = 33.0;
stSharpIQpara.stEdgeFltPara.mode_cell[m].setting[k].edgeFilter_iso[i].local_alpha = 0.5;
}
}
}
rk_aiq_user_api_asharp_SetIQPara(ctx, &stSharpIQpara);
sleep(5);
rk_aiq_user_api_asharp_GetIQPara(ctx, &stGetSharpIQpara);
for(int m = 0; m < 1; m++) {
for(int k = 0; k < 1; k++) {
for(int i = 0; i < CALIBDB_NR_SHARP_MAX_ISO_LEVEL; i++ ) {
printf("\n\n!!!!!!!!!!set:%d cell:%d !!!!!!!!!!\n", k, i);
printf("oyyf222 sharp:%f %f ratio:%f %f\n",
stGetSharpIQpara.stSharpPara.mode_cell[m].setting[k].sharp_iso[i].lratio,
stGetSharpIQpara.stSharpPara.mode_cell[m].setting[k].sharp_iso[i].hratio,
stGetSharpIQpara.stSharpPara.mode_cell[m].setting[k].sharp_iso[i].mf_sharp_ratio,
stGetSharpIQpara.stSharpPara.mode_cell[m].setting[k].sharp_iso[i].hf_sharp_ratio);
printf("oyyf222 edgefilter:%f %f\n",
stGetSharpIQpara.stEdgeFltPara.mode_cell[m].setting[k].edgeFilter_iso[i].edge_thed,
stGetSharpIQpara.stEdgeFltPara.mode_cell[m].setting[k].edgeFilter_iso[i].local_alpha);
printf("!!!!!!!!!!set:%d cell:%d end !!!!!!!!!!\n", k, i);
}
}
}
}
break;
case 'K':
printf("test mirro, flip\n");
bool mirror, flip;
rk_aiq_uapi_getMirrorFlip(ctx, &mirror, &flip);
printf("oringinal mir %d, flip %d \n", mirror, flip);
mirror = true;
flip = true;
printf("set mir %d, flip %d \n", mirror, flip);
rk_aiq_uapi_setMirroFlip(ctx, true, true, 3);
rk_aiq_uapi_getMirrorFlip(ctx, &mirror, &flip);
printf("after set mir %d, flip %d \n", mirror, flip);
break;
case 'L':
printf("test fec correct level100\n");
rk_aiq_uapi_setFecCorrectLevel(ctx, 100);
break;
case 'M':
printf("test fec correct level255\n");
rk_aiq_uapi_setFecCorrectLevel(ctx, 255);
break;
case 'N':
{
rk_aiq_dpcc_attrib_V20_t attr;
rk_aiq_user_api2_adpcc_GetAttrib(ctx, &attr);
rk_aiq_user_api2_adpcc_SetAttrib(ctx, &attr);
adebayer_attrib_t attr2;
rk_aiq_user_api2_adebayer_SetAttrib(ctx, attr2);
}
break;
case 'O':
printf("test not bypass fec\n");
rk_aiq_uapi_setFecBypass(ctx, false);
break;
case 'P':
{
int work_mode = demo_ctx->hdrmode;
rk_aiq_working_mode_t new_mode;
if (work_mode == RK_AIQ_WORKING_MODE_NORMAL)
new_mode = RK_AIQ_WORKING_MODE_ISP_HDR3;
else
new_mode = RK_AIQ_WORKING_MODE_NORMAL;
printf("switch work mode from %d to %d\n", work_mode, new_mode);
*const_cast<int*>(&demo_ctx->hdrmode) = work_mode = new_mode;
rk_aiq_uapi_sysctl_swWorkingModeDyn(ctx, new_mode);
}
break;
case 'Q':
{
rk_aiq_rotation_t rot = RK_AIQ_ROTATION_90;
rk_aiq_mems_sensor_intf_t intf = {0};
const char* main_scene = "good";
const char* sub_scene = "bad";
rk_aiq_uapi2_sysctl_setSharpFbcRotation(ctx, rot);
rk_aiq_uapi2_sysctl_setMulCamConc(ctx, true);
rk_aiq_uapi2_sysctl_regMemsSensorIntf(ctx, &intf);
rk_aiq_uapi2_sysctl_switch_scene(ctx, main_scene, sub_scene);
}
break;
case 'R':
{
rk_aiq_cpsl_info_t cpsl_info;
rk_aiq_cpsl_cap_t cpsl_cap;
rk_aiq_uapi2_sysctl_getCpsLtInfo(ctx, &cpsl_info);
rk_aiq_uapi2_sysctl_queryCpsLtCap(ctx, &cpsl_cap);
printf("sensitivity: %f, cap sensitivity: %f:%f:%f\n", cpsl_info.sensitivity,
cpsl_cap.sensitivity.min, cpsl_cap.sensitivity.step, cpsl_cap.sensitivity.max);
rk_aiq_cpsl_cfg_t cpsl_cfg;
rk_aiq_uapi2_sysctl_setCpsLtCfg(ctx, &cpsl_cfg);
}
break;
case 'S':
printf("test ldch correct level100\n");
rk_aiq_uapi_setLdchCorrectLevel(ctx, 100);
break;
case 'T':
{
rk_aiq_rect_t info;
rk_aiq_uapi2_sysctl_getCrop(ctx, &info);
printf("left:%d, top:%d, width:%d, height:%d\n", info.left, info.top, info.width, info.height);
info.left += 64;
info.top += 64;
info.width = 640;
info.height = 480;
//rk_aiq_uapi2_sysctl_setCrop(ctx, info);
}
break;
case 'U':
{
char output_dir[64] = {0};
printf("test to capture raw sync\n");
rk_aiq_uapi_debug_captureRawSync(ctx, CAPTURE_RAW_SYNC, 5, "/tmp", output_dir);
printf("Raw's storage directory is (%s)\n", output_dir);
}
break;
case 'V':
{
test_update_iqfile(demo_ctx);
}
break;
case 'W':
{
rk_aiq_ver_info_t vers;
rk_aiq_uapi2_get_version_info(&vers);
printf("aiq ver %s, parser ver %s, magic code %d, awb ver %s\n"
"ae ver %s, af ver %s, ahdr ver %s\n", vers.aiq_ver,
vers.iq_parser_ver, vers.iq_parser_magic_code,
vers.awb_algo_ver, vers.ae_algo_ver,
vers.af_algo_ver, vers.ahdr_algo_ver);
}
break;
case 'X':
{
for (int type = RK_AIQ_ALGO_TYPE_AE; type < RK_AIQ_ALGO_TYPE_MAX; type++)
{
bool ret = rk_aiq_uapi2_sysctl_getAxlibStatus(ctx, type, 0);
printf("%d is %s, \n", type, (ret ? "enabled" : "disabled or unregistered"));
const RkAiqAlgoContext* algo_ptr = rk_aiq_uapi2_sysctl_getEnabledAxlibCtx(ctx, type);
if (algo_ptr) {
printf("type: %d ==> algo_ptr: %p\n", type, algo_ptr);
}
if (ret == false) {
bool ret2 = rk_aiq_uapi2_sysctl_enableAxlib(ctx, type, 0, !ret);
}
}
}
break;
case 'Y':
{
rk_aiq_lsc_querry_info_t info;
rk_aiq_user_api2_alsc_QueryLscInfo(ctx, &info);
printf("LSC: enable: %s, \n", (info.lsc_en ? "true" : "false"));
printf("r: %d, %d, %d \n", info.r_data_tbl[0], info.r_data_tbl[1], info.r_data_tbl[2]);
printf("gr: %d, %d, %d \n", info.gr_data_tbl[0], info.gr_data_tbl[1], info.gr_data_tbl[2]);
printf("gb: %d, %d, %d \n", info.gb_data_tbl[0], info.gb_data_tbl[1], info.gb_data_tbl[2]);
printf("b: %d, %d, %d \n", info.b_data_tbl[0], info.b_data_tbl[1], info.b_data_tbl[2]);
}
break;
case 'Z':
{
rk_aiq_static_info_t info;
rk_aiq_uapi2_sysctl_enumStaticMetas(0, &info);
printf("isp version: %d, sensor name: %s\n", info.isp_hw_ver, info.sensor_info.sensor_name);
}
case '[':
set_ae_onoff(ctx, true);
printf("set ae on\n");
break;
case ']':
set_ae_onoff(ctx, false);
printf("set ae off\n");
break;
default:
break;
}
}
#endif
static void errno_exit(demo_context_t *ctx, const char *s)
{
ERR("%s: %s error %d, %s\n", get_sensor_name(ctx), s, errno, strerror(errno));
//exit(EXIT_FAILURE);
}
static int xioctl(int fh, int request, void *arg)
{
int r;
do {
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
static bool get_value_from_file(const char* path, int* value, int* frameId)
{
const char *delim = " ";
char buffer[16] = {0};
int fp;
fp = open(path, O_RDONLY | O_SYNC);
if (fp) {
if (read(fp, buffer, sizeof(buffer)) > 0) {
char *p = nullptr;
p = strtok(buffer, delim);
if (p != nullptr) {
*value = atoi(p);
p = strtok(nullptr, delim);
if (p != nullptr)
*frameId = atoi(p);
}
}
close(fp);
return true;
}
return false;
}
static int write_yuv_to_file(const void *p,
int size, int sequence, demo_context_t *ctx)
{
char file_name[64] = {0};
snprintf(file_name, sizeof(file_name),
"%s/frame%d.yuv",
ctx->yuv_dir_path,
sequence);
ctx->fp = fopen(file_name, "wb+");
if (ctx->fp == NULL) {
ERR("fopen yuv file %s failed!\n", file_name);
return -1;
}
fwrite(p, size, 1, ctx->fp);
fflush(ctx->fp);
if (ctx->fp) {
fclose(ctx->fp);
ctx->fp = NULL;
}
for (int i = 0; i < ctx->capture_yuv_num; i++)
printf("<");
printf("\n");
// printf("write frame%d yuv\n", sequence);
return 0;
}
static int creat_yuv_dir(const char* path, demo_context_t *ctx)
{
time_t now;
struct tm* timenow;
if (!path)
return -1;
time(&now);
timenow = localtime(&now);
snprintf(ctx->yuv_dir_path, sizeof(ctx->yuv_dir_path),
"%s/yuv_%04d-%02d-%02d_%02d-%02d-%02d",
path,
timenow->tm_year + 1900,
timenow->tm_mon + 1,
timenow->tm_mday,
timenow->tm_hour,
timenow->tm_min,
timenow->tm_sec);
// printf("mkdir %s for capturing yuv!\n", yuv_dir_path);
if(mkdir(ctx->yuv_dir_path, 0755) < 0) {
printf("mkdir %s error!!!\n", ctx->yuv_dir_path);
return -1;
}
ctx->_is_yuv_dir_exist = true;
return 0;
}
static void process_image(const void *p, int sequence, int size, demo_context_t *ctx)
{
if (ctx->fp && sequence >= ctx->skipCnt && ctx->outputCnt-- > 0) {
printf(">\n");
fwrite(p, size, 1, ctx->fp);
fflush(ctx->fp);
fsync(fileno(ctx->fp));
} else if (ctx->fp && sequence >= ctx->skipCnt && ctx->outputCnt-- == 0) {
fclose(ctx->fp);
ctx->fp = NULL;
} else if (ctx->writeFileSync) {
int ret = 0;
if (!ctx->is_capture_yuv) {
char file_name[32] = {0};
int rawFrameId = 0;
snprintf(file_name, sizeof(file_name), "%s/%s",
CAPTURE_RAW_PATH, CAPTURE_CNT_FILENAME);
get_value_from_file(file_name, &ctx->capture_yuv_num, &rawFrameId);
/*
* printf("%s: rawFrameId: %d, sequence: %d\n", __FUNCTION__,
* rawFrameId, sequence);
*/
sequence += 1;
if (ctx->capture_yuv_num > 0 && \
((sequence >= rawFrameId && rawFrameId > 0) || sequence < 2))
ctx->is_capture_yuv = true;
}
if (ctx->is_capture_yuv) {
if (!ctx->_is_yuv_dir_exist) {
creat_yuv_dir(DEFAULT_CAPTURE_RAW_PATH, ctx);
}
if (ctx->_is_yuv_dir_exist) {
write_yuv_to_file(p, size, sequence, ctx);
rk_aiq_uapi2_debug_captureRawNotify(ctx->aiq_ctx);
}
if (ctx->capture_yuv_num-- == 0) {
ctx->is_capture_yuv = false;
ctx->_is_yuv_dir_exist = false;
}
}
}
}
static int read_frame(demo_context_t *ctx)
{
struct v4l2_buffer buf;
int i, bytesused;
CLEAR(buf);
buf.type = ctx->buf_type;
buf.memory = V4L2_MEMORY_MMAP;
struct v4l2_plane planes[FMT_NUM_PLANES];
memset(planes, 0, sizeof(struct v4l2_plane)*FMT_NUM_PLANES);
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == ctx->buf_type) {
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
if (-1 == xioctl(ctx->fd, VIDIOC_DQBUF, &buf))
errno_exit(ctx, "VIDIOC_DQBUF");
i = buf.index;
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == ctx->buf_type)
bytesused = buf.m.planes[0].bytesused;
else
bytesused = buf.bytesused;
#if ISPDEMO_ENABLE_DRM
#ifdef ISPFEC_API
int buf_fd = -1;
void* buf_addr = NULL;
buf_fd = ctx->buffers[i].export_fd;
buf_addr = ctx->buffers[i].start;
int dstFd = g_drm_buf_pic_out.dmabuf_fd;
buf_fd = dstFd;
buf_addr = g_drm_buf_pic_out.map;
rk_ispfec_api_process(g_ispfec_ctx, ctx->buffers[i].export_fd, dstFd);
#endif
if (ctx->vop) {
int dispWidth, dispHeight;
if (ctx->width > 1920)
dispWidth = 1920;
else
dispWidth = ctx->width;
if (ctx->height > 1088)
dispHeight = 1088;
else
dispHeight = ctx->height;
#if ISPDEMO_ENABLE_RGA
if (strlen(ctx->dev_name) && strlen(ctx->dev_name2)) {
if (ctx->dev_using == 1) {
#ifdef ISPFEC_API
display_win1(buf_addr, buf_fd, RK_FORMAT_YCbCr_420_SP, dispWidth, dispHeight, 0);
#else
display_win1(ctx->buffers[i].start, ctx->buffers[i].export_fd, RK_FORMAT_YCbCr_420_SP, dispWidth, dispHeight, 0);
#endif
} else {
#ifdef ISPFEC_API
display_win2(buf_addr, buf_fd, RK_FORMAT_YCbCr_420_SP, dispWidth, dispHeight, 0);
#else
display_win2(ctx->buffers[i].start, ctx->buffers[i].export_fd, RK_FORMAT_YCbCr_420_SP, dispWidth, dispHeight, 0);
#endif
}
} else {
#else
{
#endif
drmDspFrame(ctx->width, ctx->height, dispWidth, dispHeight, ctx->buffers[i].export_fd,
ctx->buffers[i].start, DRM_FORMAT_NV12);
}
}
#endif
#ifdef ISPFEC_API
process_image(buf_addr, buf.sequence, bytesused, ctx);
#else
process_image(ctx->buffers[i].start, buf.sequence, bytesused, ctx);
#endif
if (-1 == xioctl(ctx->fd, VIDIOC_QBUF, &buf))
errno_exit(ctx, "VIDIOC_QBUF");
return 1;
}
static int read_frame_pp_oneframe(demo_context_t *ctx)
{
struct v4l2_buffer buf;
struct v4l2_buffer buf_pp;
int i, ii = 0, bytesused;
static int first_time = 1;
CLEAR(buf);
// dq one buf from isp mp
DBG("------ dq 1 from isp mp --------------\n");
buf.type = ctx->buf_type;
buf.memory = V4L2_MEMORY_MMAP;
struct v4l2_plane planes[FMT_NUM_PLANES];
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == ctx->buf_type) {
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
if (-1 == xioctl(ctx->fd_isp_mp, VIDIOC_DQBUF, &buf))
errno_exit(ctx, "VIDIOC_DQBUF");
i = buf.index;
if (first_time ) {
DBG("------ dq 2 from isp mp --------------\n");
if (-1 == xioctl(ctx->fd_isp_mp, VIDIOC_DQBUF, &buf))
errno_exit(ctx, "VIDIOC_DQBUF");
ii = buf.index;
}
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == ctx->buf_type)
bytesused = buf.m.planes[0].bytesused;
else
bytesused = buf.bytesused;
// queue to ispp input
DBG("------ queue 1 index %d to ispp input --------------\n", i);
CLEAR(buf_pp);
buf_pp.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
buf_pp.memory = V4L2_MEMORY_DMABUF;
buf_pp.index = i;
struct v4l2_plane planes_pp[FMT_NUM_PLANES];
memset(planes_pp, 0, sizeof(planes_pp));
buf_pp.m.planes = planes_pp;
buf_pp.length = FMT_NUM_PLANES;
buf_pp.m.planes[0].m.fd = ctx->buffers_mp[i].export_fd;
if (-1 == xioctl(ctx->fd_pp_input, VIDIOC_QBUF, &buf_pp))
errno_exit(ctx, "VIDIOC_QBUF");
if (first_time ) {
DBG("------ queue 2 index %d to ispp input --------------\n", ii);
buf_pp.index = ii;
buf_pp.m.planes[0].m.fd = ctx->buffers_mp[ii].export_fd;
if (-1 == xioctl(ctx->fd_pp_input, VIDIOC_QBUF, &buf_pp))
errno_exit(ctx, "VIDIOC_QBUF");
}
// read frame from ispp sharp/scale
DBG("------ readframe from output --------------\n");
read_frame(ctx);
// dq from pp input
DBG("------ dq 1 from ispp input--------------\n");
if (-1 == xioctl(ctx->fd_pp_input, VIDIOC_DQBUF, &buf_pp))
errno_exit(ctx, "VIDIOC_DQBUF");
// queue back to mp
DBG("------ queue 1 index %d back to isp mp--------------\n", buf_pp.index);
buf.index = buf_pp.index;
if (-1 == xioctl(ctx->fd_isp_mp, VIDIOC_QBUF, &buf))
errno_exit(ctx, "VIDIOC_QBUF");
first_time = 0;
return 1;
}
static void mainloop(demo_context_t *ctx)
{
while ((ctx->frame_count == -1) || (ctx->frame_count-- > 0)) {
if (ctx->pponeframe)
read_frame_pp_oneframe(ctx);
else
read_frame(ctx);
}
}
static void stop_capturing(demo_context_t *ctx)
{
enum v4l2_buf_type type;
type = ctx->buf_type;
if (-1 == xioctl(ctx->fd, VIDIOC_STREAMOFF, &type))
errno_exit(ctx, "VIDIOC_STREAMOFF");
}
static void stop_capturing_pp_oneframe(demo_context_t *ctx)
{
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
if (-1 == xioctl(ctx->fd_pp_input, VIDIOC_STREAMOFF, &type))
errno_exit(ctx, "VIDIOC_STREAMOFF ppinput");
type = ctx->buf_type;
if (-1 == xioctl(ctx->fd_isp_mp, VIDIOC_STREAMOFF, &type))
errno_exit(ctx, "VIDIOC_STREAMOFF ispmp");
}
static void start_capturing(demo_context_t *ctx)
{
unsigned int i;
enum v4l2_buf_type type;
for (i = 0; i < ctx->n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = ctx->buf_type;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == ctx->buf_type) {
struct v4l2_plane planes[FMT_NUM_PLANES];
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
if (-1 == xioctl(ctx->fd, VIDIOC_QBUF, &buf))
errno_exit(ctx, "VIDIOC_QBUF");
}
type = ctx->buf_type;
DBG("%s:-------- stream on output -------------\n", get_sensor_name(ctx));
if (-1 == xioctl(ctx->fd, VIDIOC_STREAMON, &type))
errno_exit(ctx, "VIDIOC_STREAMON");
}
static void start_capturing_pp_oneframe(demo_context_t *ctx)
{
unsigned int i;
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
DBG("%s:-------- stream on pp input -------------\n", get_sensor_name(ctx));
if (-1 == xioctl(ctx->fd_pp_input, VIDIOC_STREAMON, &type))
errno_exit(ctx, "VIDIOC_STREAMON pp input");
type = ctx->buf_type;
for (i = 0; i < ctx->n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = ctx->buf_type;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == ctx->buf_type) {
struct v4l2_plane planes[FMT_NUM_PLANES];
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
if (-1 == xioctl(ctx->fd_isp_mp, VIDIOC_QBUF, &buf))
errno_exit(ctx, "VIDIOC_QBUF");
}
DBG("%s:-------- stream on isp mp -------------\n", get_sensor_name(ctx));
if (-1 == xioctl(ctx->fd_isp_mp, VIDIOC_STREAMON, &type))
errno_exit(ctx, "VIDIOC_STREAMON ispmp");
}
static void uninit_device(demo_context_t *ctx)
{
unsigned int i;
if (ctx->n_buffers == 0)
return;
for (i = 0; i < ctx->n_buffers; ++i) {
if (-1 == munmap(ctx->buffers[i].start, ctx->buffers[i].length))
errno_exit(ctx, "munmap");
close(ctx->buffers[i].export_fd);
}
free(ctx->buffers);
ctx->n_buffers = 0;
}
static void uninit_device_pp_oneframe(demo_context_t *ctx)
{
unsigned int i;
for (i = 0; i < ctx->n_buffers; ++i) {
if (-1 == munmap(ctx->buffers_mp[i].start, ctx->buffers_mp[i].length))
errno_exit(ctx, "munmap");
close(ctx->buffers_mp[i].export_fd);
}
free(ctx->buffers_mp);
}
static void init_mmap(int pp_onframe, demo_context_t *ctx)
{
struct v4l2_requestbuffers req;
int fd_tmp = -1;
CLEAR(req);
if (pp_onframe)
fd_tmp = ctx->fd_isp_mp ;
else
fd_tmp = ctx->fd;
req.count = BUFFER_COUNT;
req.type = ctx->buf_type;
req.memory = V4L2_MEMORY_MMAP;
struct buffer *tmp_buffers = NULL;
if (-1 == xioctl(fd_tmp, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
ERR("%s: %s does not support "
"memory mapping\n", get_sensor_name(ctx), get_dev_name(ctx));
//exit(EXIT_FAILURE);
} else {
errno_exit(ctx, "VIDIOC_REQBUFS");
}
}
if (req.count < 2) {
ERR("%s: Insufficient buffer memory on %s\n", get_sensor_name(ctx),
get_dev_name(ctx));
//exit(EXIT_FAILURE);
}
tmp_buffers = (struct buffer*)calloc(req.count, sizeof(struct buffer));
if (!tmp_buffers) {
ERR("%s: Out of memory\n", get_sensor_name(ctx));
//exit(EXIT_FAILURE);
}
if (pp_onframe)
ctx->buffers_mp = tmp_buffers;
else
ctx->buffers = tmp_buffers;
for (ctx->n_buffers = 0; ctx->n_buffers < req.count; ++ctx->n_buffers) {
struct v4l2_buffer buf;
struct v4l2_plane planes[FMT_NUM_PLANES];
CLEAR(buf);
CLEAR(planes);
buf.type = ctx->buf_type;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = ctx->n_buffers;
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == ctx->buf_type) {
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
if (-1 == xioctl(fd_tmp, VIDIOC_QUERYBUF, &buf))
errno_exit(ctx, "VIDIOC_QUERYBUF");
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == ctx->buf_type) {
tmp_buffers[ctx->n_buffers].length = buf.m.planes[0].length;
tmp_buffers[ctx->n_buffers].start =
mmap(NULL /* start anywhere */,
buf.m.planes[0].length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */,
fd_tmp, buf.m.planes[0].m.mem_offset);
} else {
tmp_buffers[ctx->n_buffers].length = buf.length;
tmp_buffers[ctx->n_buffers].start =
mmap(NULL /* start anywhere */,
buf.length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */,
fd_tmp, buf.m.offset);
}
if (MAP_FAILED == tmp_buffers[ctx->n_buffers].start)
errno_exit(ctx, "mmap");
// export buf dma fd
struct v4l2_exportbuffer expbuf;
xcam_mem_clear (expbuf);
expbuf.type = ctx->buf_type;
expbuf.index = ctx->n_buffers;
expbuf.flags = O_CLOEXEC;
if (xioctl(fd_tmp, VIDIOC_EXPBUF, &expbuf) < 0) {
errno_exit(ctx, "get dma buf failed\n");
} else {
DBG("%s: get dma buf(%d)-fd: %d\n", get_sensor_name(ctx), ctx->n_buffers, expbuf.fd);
}
tmp_buffers[ctx->n_buffers].export_fd = expbuf.fd;
}
}
static void init_input_dmabuf_oneframe(demo_context_t *ctx) {
struct v4l2_requestbuffers req;
CLEAR(req);
printf("%s:-------- request pp input buffer -------------\n", get_sensor_name(ctx));
req.count = BUFFER_COUNT;
req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
req.memory = V4L2_MEMORY_DMABUF;
if (-1 == xioctl(ctx->fd_pp_input, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
ERR("does not support "
"DMABUF\n");
exit(EXIT_FAILURE);
} else {
errno_exit(ctx, "VIDIOC_REQBUFS");
}
}
if (req.count < 2) {
ERR("Insufficient buffer memory on %s\n",
get_dev_name(ctx));
exit(EXIT_FAILURE);
}
printf("%s:-------- request isp mp buffer -------------\n", get_sensor_name(ctx));
init_mmap(true, ctx);
}
static void init_device(demo_context_t *ctx)
{
struct v4l2_capability cap;
struct v4l2_format fmt;
if (-1 == xioctl(ctx->fd, VIDIOC_QUERYCAP, &cap)) {
if (EINVAL == errno) {
ERR("%s: %s is no V4L2 device\n", get_sensor_name(ctx),
get_dev_name(ctx));
//exit(EXIT_FAILURE);
} else {
errno_exit(ctx, "VIDIOC_QUERYCAP");
}
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) {
ERR("%s: %s is not a video capture device, capabilities: %x\n",
get_sensor_name(ctx), get_dev_name(ctx), cap.capabilities);
//exit(EXIT_FAILURE);
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
ERR("%s: %s does not support streaming i/o\n", get_sensor_name(ctx),
get_dev_name(ctx));
//exit(EXIT_FAILURE);
}
if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
ctx->buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
CLEAR(fmt);
fmt.type = ctx->buf_type;
fmt.fmt.pix.width = ctx->width;
fmt.fmt.pix.height = ctx->height;
fmt.fmt.pix.pixelformat = ctx->format;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ctx->limit_range)
fmt.fmt.pix.quantization = V4L2_QUANTIZATION_LIM_RANGE;
else
fmt.fmt.pix.quantization = V4L2_QUANTIZATION_FULL_RANGE;
} else if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) {
ctx->buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
CLEAR(fmt);
fmt.type = ctx->buf_type;
fmt.fmt.pix_mp.width = ctx->width;
fmt.fmt.pix_mp.height = ctx->height;
fmt.fmt.pix_mp.pixelformat = ctx->format;
fmt.fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
if (ctx->limit_range)
fmt.fmt.pix_mp.quantization = V4L2_QUANTIZATION_LIM_RANGE;
else
fmt.fmt.pix_mp.quantization = V4L2_QUANTIZATION_FULL_RANGE;
}
if (-1 == xioctl(ctx->fd, VIDIOC_S_FMT, &fmt))
errno_exit(ctx, "VIDIOC_S_FMT");
init_mmap(false, ctx);
}
static void init_device_pp_oneframe(demo_context_t *ctx)
{
// TODO, set format and link, now do with setup_link.sh
init_input_dmabuf_oneframe(ctx);
}
static void close_device(demo_context_t *ctx)
{
if (-1 == close(ctx->fd))
errno_exit(ctx, "close");
ctx->fd = -1;
}
static void open_device(demo_context_t *ctx)
{
printf("-------- open output dev_name:%s -------------\n", get_dev_name(ctx));
ctx->fd = open(get_dev_name(ctx), O_RDWR /* required */ /*| O_NONBLOCK*/, 0);
if (-1 == ctx->fd) {
ERR("Cannot open '%s': %d, %s\n",
get_dev_name(ctx), errno, strerror(errno));
exit(EXIT_FAILURE);
}
}
static void close_device_pp_oneframe(demo_context_t *ctx)
{
if (-1 == close(ctx->fd_pp_input))
errno_exit(ctx, "close");
ctx->fd_pp_input = -1;
if (-1 == close(ctx->fd_isp_mp))
errno_exit(ctx, "close");
ctx->fd_isp_mp = -1;
}
static void open_device_pp_oneframe(demo_context_t *ctx)
{
printf("-------- open pp input(video13) -------------\n");
ctx->fd_pp_input = open("/dev/video13", O_RDWR /* required */ /*| O_NONBLOCK*/, 0);
if (-1 == ctx->fd_pp_input) {
ERR("Cannot open '%s': %d, %s\n",
get_dev_name(ctx), errno, strerror(errno));
exit(EXIT_FAILURE);
}
printf("-------- open isp mp(video0) -------------\n");
ctx->fd_isp_mp = open("/dev/video0", O_RDWR /* required */ /*| O_NONBLOCK*/, 0);
if (-1 == ctx->fd_isp_mp ) {
ERR("Cannot open '%s': %d, %s\n",
get_dev_name(ctx), errno, strerror(errno));
exit(EXIT_FAILURE);
}
}
static void uninit_device_pp_onframe(demo_context_t *ctx)
{
unsigned int i;
for (i = 0; i < ctx->n_buffers; ++i) {
if (-1 == munmap(ctx->buffers_mp[i].start, ctx->buffers_mp[i].length))
errno_exit(ctx, "munmap");
close(ctx->buffers_mp[i].export_fd);
}
free(ctx->buffers_mp);
}
static void parse_args(int argc, char **argv, demo_context_t *ctx)
{
int c;
int digit_optind = 0;
optind = 0;
while (1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"width", required_argument, 0, 'w' },
{"height", required_argument, 0, 'h' },
{"format", required_argument, 0, 'f' },
{"device", required_argument, 0, 'd' },
{"device2", required_argument, 0, 'i' },
{"device3", required_argument, 0, 'g' },
{"device4", required_argument, 0, 'j' },
{"stream-to", required_argument, 0, 'o' },
{"stream-count", required_argument, 0, 'n' },
{"stream-skip", required_argument, 0, 'k' },
{"count", required_argument, 0, 'c' },
{"help", no_argument, 0, 'p' },
{"silent", no_argument, 0, 's' },
{"vop", no_argument, 0, 'v' },
{"rkaiq", no_argument, 0, 'r' },
{"pponeframe", no_argument, 0, 'm' },
{"hdr", required_argument, 0, 'a' },
{"sync-to-raw", no_argument, 0, 'e' },
{"limit", no_argument, 0, 'l' },
{"ctl", required_argument, 0, 't' },
{"iqpath", required_argument, 0, '1' },
{"orp", required_argument, 0, '2' },
//{"sensor", required_argument, 0, 'b' },
{"camgroup", no_argument, 0, '3' },
{0, 0, 0, 0 }
};
//c = getopt_long(argc, argv, "w:h:f:i:d:o:c:ps",
c = getopt_long(argc, argv, "w:h:f:i:g:j:d:o:c:n:k:a:t:1:2:3mpsevrl",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'c':
ctx->frame_count = atoi(optarg);
break;
case 'w':
ctx->width = atoi(optarg);
break;
case 'h':
ctx->height = atoi(optarg);
break;
case 'f':
ctx->format = v4l2_fourcc(optarg[0], optarg[1], optarg[2], optarg[3]);
break;
case 'd':
strcpy(ctx->dev_name, optarg);
break;
case 'i':
strcpy(ctx->dev_name2, optarg);
break;
case 'g':
strcpy(ctx->dev_name3, optarg);
break;
case 'j':
strcpy(ctx->dev_name4, optarg);
break;
case 'o':
strcpy(ctx->out_file, optarg);
ctx->writeFile = 1;
break;
case 'n':
ctx->outputCnt = atoi(optarg);
break;
case 'k':
ctx->skipCnt = atoi(optarg);
break;
case 's':
silent = 1;
break;
case 'v':
ctx->vop = 1;
break;
case 'r':
ctx->rkaiq = 1;
break;
case 'm':
ctx->pponeframe = 1;
break;
case 'a':
ctx->hdrmode = atoi(optarg);
break;
case 'e':
ctx->writeFileSync = 1;
break;
case 'l':
ctx->limit_range = 1;
break;
case '1':
strcpy(ctx->iqpath, optarg);
break;
case '2':
{
// parse raw fmt
char* raw_dir = strstr(optarg, ",");
size_t raw_dir_str_len = raw_dir - optarg;
if (!raw_dir) {
printf("orp dir error ! \n");
exit(-1);
}
strncpy(ctx->orppath, optarg, raw_dir_str_len);
char* raw_fmt_w_start = raw_dir + 1;
int raw_width = atoi(raw_fmt_w_start);
if (raw_width == 0) {
printf("orp raw_width error ! \n");
exit(-1);
}
ctx->orpRawW = raw_width;
char* raw_fmt_h_start = strstr(raw_fmt_w_start, ":") + 1;
if (!raw_fmt_h_start) {
printf("orp raw_h error ! \n");
exit(-1);
}
int raw_height = atoi(raw_fmt_h_start);
ctx->orpRawH = raw_height;
char* raw_fmt_pix_start = strstr(raw_fmt_h_start, ":") + 1;
strcpy(ctx->orpRawFmt, raw_fmt_pix_start);
printf("orp_path:%s, w:%d,h:%d, pix:%s \n",
ctx->orppath, raw_width, raw_height, raw_fmt_pix_start);
ctx->isOrp = true;
}
break;
case 't':
ctx->ctl_type = atoi(optarg);
break;
case '3':
ctx->camGroup = true;
break;
case '?':
case 'p':
ERR("Usage: %s to capture rkisp1 frames\n"
" --width, default 640, optional, width of image\n"
" --height, default 480, optional, height of image\n"
" --format, default NV12, optional, fourcc of format\n"
" --count, default 1000, optional, how many frames to capture\n"
" --device, required, path of video device1\n"
" --device2, required, path of video device2\n"
" --device3, required, path of video device3\n"
" --device4, required, path of video device4\n"
" --stream-to, optional, output file path, if <file> is '-', then the data is written to stdout\n"
" --stream-count, default 3 optional, how many frames to write files\n"
" --stream-skip, default 30 optional, how many frames to skip befor writing file\n"
" --vop, optional, drm display\n"
" --rkaiq, optional, auto image quality\n"
" --silent, optional, subpress debug log\n"
" --pponeframe, optional, pp oneframe readback mode\n"
" --hdr <val>, optional, hdr mode, val 2 means hdrx2, 3 means hdrx3 \n"
" --sync-to-raw, optional, write yuv files in sync with raw\n"
" --limit, optional, yuv limit range\n"
" --ctl <val>, optional, sysctl procedure test \n"
" --iqpath <val>, optional, absolute path of iq file dir \n"
" --orp <raw_dir,w:h:raw_fmt>, optional, absolute path of raw files dir \n"
" raw_fmt: BG10 -> SBGGR10, GB10 -> SGBRG10 \n"
" BA10 -> SGRBG10, RG10 -> SRGGB10 \n"
" --sensor, default os04a10, optional, sensor names\n",
argv[0]);
exit(-1);
default:
ERR("?? getopt returned character code 0%o ??\n", c);
}
}
if (strlen(ctx->dev_name) == 0) {
ERR("%s: arguments --output and --device are required\n", get_sensor_name(ctx));
//exit(-1);
}
}
static void deinit(demo_context_t *ctx)
{
//if (!ctx->camgroup_ctx)
stop_capturing(ctx);
if (ctx->pponeframe)
stop_capturing_pp_oneframe(ctx);
if (ctx->aiq_ctx) {
printf("%s:-------- stop aiq -------------\n", get_sensor_name(ctx));
rk_aiq_uapi2_sysctl_stop(ctx->aiq_ctx, false);
} else if (ctx->camgroup_ctx) {
if (ctx->dev_using == 1) {
printf("%s:-------- stop aiq camgroup -------------\n", get_sensor_name(ctx));
rk_aiq_uapi2_camgroup_stop(ctx->camgroup_ctx);
#ifdef CUSTOM_GROUP_AE_DEMO_TEST
rk_aiq_uapi2_customAE_unRegister((const rk_aiq_sys_ctx_t*)(ctx->camgroup_ctx));
#endif
#ifdef CUSTOM_GROUP_AWB_DEMO_TEST
rk_aiq_uapi2_customAWB_unRegister((const rk_aiq_sys_ctx_t*)(ctx->camgroup_ctx));
#endif
}
}
if (ctx->aiq_ctx) {
printf("%s:-------- deinit aiq -------------\n", get_sensor_name(ctx));
#ifdef CUSTOM_AE_DEMO_TEST
//rk_aiq_AELibunRegCallBack(ctx->aiq_ctx, 0);
rk_aiq_uapi2_customAE_unRegister(ctx->aiq_ctx);
#endif
#ifdef CUSTOM_AWB_DEMO_TEST
//rk_aiq_AELibunRegCallBack(ctx->aiq_ctx, 0);
rk_aiq_uapi2_customAWB_unRegister(ctx->aiq_ctx);
#endif
rk_aiq_uapi2_sysctl_deinit(ctx->aiq_ctx);
printf("%s:-------- deinit aiq end -------------\n", get_sensor_name(ctx));
} else if (ctx->camgroup_ctx) {
if (ctx->dev_using == 1) {
printf("%s:-------- deinit aiq camgroup -------------\n", get_sensor_name(ctx));
rk_aiq_uapi2_camgroup_destroy(ctx->camgroup_ctx);
ctx->camgroup_ctx = NULL;
printf("%s:-------- deinit aiq camgroup end -------------\n", get_sensor_name(ctx));
}
}
#ifdef ISPFEC_API
rk_ispfec_api_deinit(g_ispfec_ctx);
g_ispfec_ctx = NULL;
#endif
uninit_device(ctx);
if (ctx->pponeframe)
uninit_device_pp_oneframe(ctx);
close_device(ctx);
if (ctx->pponeframe)
close_device_pp_oneframe(ctx);
if (ctx->fp)
fclose(ctx->fp);
}
static void signal_handle(int signo)
{
printf("force exit signo %d !!!\n", signo);
if (g_main_ctx) {
g_main_ctx->frame_count = 0;
stop_capturing(g_main_ctx);
if (g_main_ctx->camGroup && g_second_ctx)
stop_capturing(g_second_ctx);
deinit(g_main_ctx);
g_main_ctx = NULL;
}
if (g_second_ctx) {
g_second_ctx->frame_count = 0;
deinit(g_second_ctx);
g_second_ctx = NULL;
}
exit(0);
}
static void* test_thread(void* args) {
pthread_detach (pthread_self());
disable_terminal_return();
printf("begin test imgproc\n");
while(!_if_quit) {
// test_imgproc((demo_context_t*) args);
sample_main(args);
}
printf("end test imgproc\n");
restore_terminal_settings();
return 0;
}
static void* test_offline_thread(void* args) {
pthread_detach (pthread_self());
demo_context_t* demo_ctx = (demo_context_t*) args;
DIR* dir = opendir(demo_ctx->orppath);
struct dirent* dir_ent = NULL;
std::vector<std::string> raw_files;
if (dir) {
while ((dir_ent = readdir(dir))) {
if (dir_ent->d_type == DT_REG) {
// is raw file
if (strstr(dir_ent->d_name, ".raw")) {
raw_files.push_back(dir_ent->d_name);
}
}
}
closedir(dir);
}
std::sort(raw_files.begin(), raw_files.end(),
[](std::string str1, std::string str2) -> bool {
std::string::size_type sz;
int ind1 = std::stoi(str1, &sz);
int ind2 = std::stoi(str2, &sz);
return ind1 < ind2 ? true : false;
});
while (!demo_ctx->orpStop) {
for (auto raw_file : raw_files) {
std::string full_name = demo_ctx->orppath + raw_file;
printf("process raw : %s \n", full_name.c_str());
rk_aiq_uapi2_sysctl_enqueueRkRawFile(demo_ctx->aiq_ctx, full_name.c_str());
//usleep(500000);
}
usleep(500000);
}
demo_ctx->orpStopped = true;
return 0;
}
#if 0
static int set_ae_onoff(const rk_aiq_sys_ctx_t* ctx, bool onoff)
{
XCamReturn ret = XCAM_RETURN_NO_ERROR;
Uapi_ExpSwAttr_t expSwAttr;
ret = rk_aiq_user_api_ae_getExpSwAttr(ctx, &expSwAttr);
expSwAttr.enable = onoff;
ret = rk_aiq_user_api_ae_setExpSwAttr(ctx, expSwAttr);
return 0;
}
#endif
static int query_ae_state(const rk_aiq_sys_ctx_t* ctx)
{
XCamReturn ret = XCAM_RETURN_NO_ERROR;
Uapi_ExpQueryInfo_t queryInfo;
ret = rk_aiq_user_api2_ae_queryExpResInfo(ctx, &queryInfo);
printf("ae IsConverged: %d\n", queryInfo.IsConverged);
return 0;
}
static void set_af_manual_meascfg(const rk_aiq_sys_ctx_t* ctx)
{
rk_aiq_af_attrib_t attr;
uint16_t gamma_y[RKAIQ_RAWAF_GAMMA_NUM] =
{0, 45, 108, 179, 245, 344, 409, 459, 500, 567, 622, 676, 759, 833, 896, 962, 1023};
rk_aiq_user_api2_af_GetAttrib(ctx, &attr);
attr.AfMode = RKAIQ_AF_MODE_FIXED;
attr.manual_meascfg.contrast_af_en = 1;
attr.manual_meascfg.rawaf_sel = 0; // normal = 0; hdr = 1
attr.manual_meascfg.window_num = 2;
attr.manual_meascfg.wina_h_offs = 2;
attr.manual_meascfg.wina_v_offs = 2;
attr.manual_meascfg.wina_h_size = 2580;
attr.manual_meascfg.wina_v_size = 1935;
attr.manual_meascfg.winb_h_offs = 1146;
attr.manual_meascfg.winb_v_offs = 972;
attr.manual_meascfg.winb_h_size = 300;
attr.manual_meascfg.winb_v_size = 300;
attr.manual_meascfg.gamma_flt_en = 1;
memcpy(attr.manual_meascfg.gamma_y, gamma_y, RKAIQ_RAWAF_GAMMA_NUM * sizeof(uint16_t));
attr.manual_meascfg.gaus_flt_en = 1;
attr.manual_meascfg.gaus_h0 = 0x20;
attr.manual_meascfg.gaus_h1 = 0x10;
attr.manual_meascfg.gaus_h2 = 0x08;
attr.manual_meascfg.afm_thres = 4;
attr.manual_meascfg.lum_var_shift[0] = 0;
attr.manual_meascfg.afm_var_shift[0] = 0;
attr.manual_meascfg.lum_var_shift[1] = 4;
attr.manual_meascfg.afm_var_shift[1] = 4;
attr.manual_meascfg.sp_meas.enable = true;
attr.manual_meascfg.sp_meas.ldg_xl = 10;
attr.manual_meascfg.sp_meas.ldg_yl = 28;
attr.manual_meascfg.sp_meas.ldg_kl = (255 - 28) * 256 / 45;
attr.manual_meascfg.sp_meas.ldg_xh = 118;
attr.manual_meascfg.sp_meas.ldg_yh = 8;
attr.manual_meascfg.sp_meas.ldg_kh = (255 - 8) * 256 / 15;
attr.manual_meascfg.sp_meas.highlight_th = 245;
attr.manual_meascfg.sp_meas.highlight2_th = 200;
rk_aiq_user_api2_af_SetAttrib(ctx, &attr);
}
static void print_af_stats(rk_aiq_isp_stats_t *stats_ref)
{
unsigned long sof_time;
if (stats_ref->frame_id % 30 != 0)
return;
sof_time = stats_ref->af_stats.sof_tim / 1000000LL;
printf("sof_tim %ld, sharpness roia: 0x%llx-0x%08x roib: 0x%x-0x%08x\n",
sof_time,
stats_ref->af_stats.roia_sharpness,
stats_ref->af_stats.roia_luminance,
stats_ref->af_stats.roib_sharpness,
stats_ref->af_stats.roib_luminance);
printf("global_sharpness\n");
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
printf("0x%08x, ", stats_ref->af_stats.global_sharpness[15 * i + j]);
}
printf("\n");
}
printf("lowpass_fv4_4\n");
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
printf("0x%08x, ", stats_ref->af_stats.lowpass_fv4_4[15 * i + j]);
}
printf("\n");
}
printf("lowpass_fv8_8\n");
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
printf("0x%08x, ", stats_ref->af_stats.lowpass_fv8_8[15 * i + j]);
}
printf("\n");
}
printf("lowpass_highlht\n");
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
printf("0x%08x, ", stats_ref->af_stats.lowpass_highlht[15 * i + j]);
}
printf("\n");
}
printf("lowpass_highlht2\n");
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
printf("0x%08x, ", stats_ref->af_stats.lowpass_highlht2[15 * i + j]);
}
printf("\n");
}
}
static void* stats_thread(void* args) {
demo_context_t* ctx = (demo_context_t*)args;
XCamReturn ret;
pthread_detach (pthread_self());
printf("begin stats thread\n");
set_af_manual_meascfg(ctx->aiq_ctx);
while(1) {
rk_aiq_isp_stats_t *stats_ref = NULL;
ret = rk_aiq_uapi2_sysctl_get3AStatsBlk(ctx->aiq_ctx, &stats_ref, -1);
if (ret == XCAM_RETURN_NO_ERROR && stats_ref != NULL) {
printf("get one stats frame id %d \n", stats_ref->frame_id);
query_ae_state(ctx->aiq_ctx);
print_af_stats(stats_ref);
rk_aiq_uapi2_sysctl_release3AStatsRef(ctx->aiq_ctx, stats_ref);
} else {
if (ret == XCAM_RETURN_NO_ERROR) {
printf("aiq has stopped !\n");
break;
} else if (ret == XCAM_RETURN_ERROR_TIMEOUT) {
printf("aiq timeout!\n");
continue;
} else if (ret == XCAM_RETURN_ERROR_FAILED) {
printf("aiq failed!\n");
break;
}
}
}
printf("end stats thread\n");
return 0;
}
void release_buffer(void *addr) {
printf("release buffer called: addr=%p\n", addr);
}
static void test_tuning_api(demo_context_t *ctx)
{
/* Sample code of API rk_aiq_uapi2_sysctl_tuning
* This API replaces current iq params through JsonPatch.
* 1. Must be called after Api rk_aiq_uapi2_sysctl_init, prefer to be
* called before rk_aiq_uapi2_sysctl_prepare
* 2. Notice that this API only replaces the current iq params in use, and
* the iq file would not be modified.
* Supported path including:
* path/sensor_calib
* /module_calib
* And submodules in node 'scene_isp30' , such as
* /wb_v21 notice that not /main_scene/0/sbu_scene/0/wb_v21, cause
* there is no scene contex for in-use iq params.
* 'path' could refer to iq json file
* 3.
* 3.1 Prefer to replace the all params of same iq node in one JsonPatch
* 3.2 prefer to replace the params of diffrent iq node in separate JsonPatch
* 4. JsonPatch string format:
* [// '[' start syntax
* { // each 'op' embraced by '{}'
"op": "replace", // Fixed syntax
"path": // node path in Json iq file
"value": // Note: All chidren's valuse should be specified for the 'path', otherwise those unspecified ones
// may be uninitialzed.
* }, { // ',' for next 'op'
* } // Note: no ',' for last 'op'
* ]// ']' end syntax
*/
// example 1: replace sensor info
// 1. Show how to repalce the non-leaf node "sensor_calib/resolution"
// values should be embraced by '{}' for non-leaf node, and all children should be set.
// 2. Show how to replace the values for multiple sub nodes of same parent in one JsonPatch
std::string json_sensor_str = " \n\
[{ \n\
\"op\":\"replace\", \n\
\"path\": \"/sensor_calib/resolution\", \n\
\"value\": \n\
{ \"width\": 2222, \"height\": 2160} \n\
}, { \n\
\"op\":\"replace\", \n\
\"path\": \"/sensor_calib/CISFlip\", \n\
\"value\": 6\n\
}]";
printf("%s\n", json_sensor_str.c_str());
rk_aiq_uapi2_sysctl_tuning(ctx->aiq_ctx, const_cast<char*>(json_sensor_str.c_str()));
// example 2: replace awb info
// 1. Show how to replace the values for type array
// value shoulde be embraced by '[]' for type array, and the target
// length of the array should be unchanged.
// 2. Show how to replace the value for one array item
// the path for array item is: array name/array index/
std::string json_awb_str = " \n\
[{ \n\
\"op\":\"replace\", \n\
\"path\": \"/wb_v21/autoExtPara/wbGainClip/cct\", \n\
\"value\": \n\
[100,200,300,40,50,60] \n\
},{ \n\
\"op\":\"replace\", \n\
\"path\": \"/wb_v21/autoPara/lightSources/0/name\", \n\
\"value\": \"aaaaaaaaa\" \n\
}]";
printf("%s\n", json_awb_str.c_str());
rk_aiq_uapi2_sysctl_tuning(ctx->aiq_ctx, const_cast<char*>(json_awb_str.c_str()));
printf("%s done ..\n", __func__);
}
static void rkisp_routine(demo_context_t *ctx)
{
char sns_entity_name[64];
rk_aiq_working_mode_t work_mode = RK_AIQ_WORKING_MODE_NORMAL;
if (ctx->hdrmode == 2)
work_mode = RK_AIQ_WORKING_MODE_ISP_HDR2;
else if (ctx->hdrmode == 3)
work_mode = RK_AIQ_WORKING_MODE_ISP_HDR3;
printf("work_mode %d\n", work_mode);
strcpy(sns_entity_name, rk_aiq_uapi2_sysctl_getBindedSnsEntNmByVd(get_dev_name(ctx)));
printf("sns_entity_name:%s\n", sns_entity_name);
sscanf(&sns_entity_name[6], "%s", ctx->sns_name);
printf("sns_name:%s\n", ctx->sns_name);
rk_aiq_static_info_t s_info;
rk_aiq_uapi2_sysctl_getStaticMetas(sns_entity_name, &s_info);
// check if hdr mode is supported
if (work_mode != 0) {
bool b_work_mode_supported = false;
rk_aiq_sensor_info_t* sns_info = &s_info.sensor_info;
for (int i = 0; i < SUPPORT_FMT_MAX; i++)
// TODO, should decide the resolution firstly,
// then check if the mode is supported on this
// resolution
if ((sns_info->support_fmt[i].hdr_mode == 5/*HDR_X2*/ &&
work_mode == RK_AIQ_WORKING_MODE_ISP_HDR2) ||
(sns_info->support_fmt[i].hdr_mode == 6/*HDR_X3*/ &&
work_mode == RK_AIQ_WORKING_MODE_ISP_HDR3)) {
b_work_mode_supported = true;
break;
}
if (!b_work_mode_supported) {
printf("\nWARNING !!!"
"work mode %d is not supported, changed to normal !!!\n\n",
work_mode);
work_mode = RK_AIQ_WORKING_MODE_NORMAL;
}
}
printf("%s:-------- open output dev -------------\n", get_sensor_name(ctx));
open_device(ctx);
if (ctx->pponeframe)
open_device_pp_oneframe(ctx);
if (ctx->writeFile) {
ctx->fp = fopen(ctx->out_file, "w+");
if (ctx->fp == NULL) {
ERR("%s: fopen output file %s failed!\n", get_sensor_name(ctx), ctx->out_file);
}
}
if (ctx->rkaiq) {
XCamReturn ret = XCAM_RETURN_NO_ERROR;
rk_aiq_tb_info_t tb_info;
tb_info.magic = sizeof(rk_aiq_tb_info_t) - 2;
tb_info.is_pre_aiq = false;
ret = rk_aiq_uapi2_sysctl_preInit_tb_info(sns_entity_name, &tb_info);
if (work_mode == RK_AIQ_WORKING_MODE_NORMAL)
ret = rk_aiq_uapi2_sysctl_preInit_scene(sns_entity_name, "normal", "day");
else
ret = rk_aiq_uapi2_sysctl_preInit_scene(sns_entity_name, "hdr", "day");
if (ret < 0)
ERR("%s: failed to set %s scene\n",
get_sensor_name(ctx),
work_mode == RK_AIQ_WORKING_MODE_NORMAL ? "normal" : "hdr");
if (strlen(ctx->iqpath))
{
if (!ctx->camGroup)
ctx->aiq_ctx = rk_aiq_uapi2_sysctl_init(sns_entity_name, ctx->iqpath, NULL, NULL);
else {
// create once for mulitple cams
if (ctx->dev_using == 1) {
char sns_entity_name2[64] = {'\0'};
bool has_dev2 = false;
if (strlen(ctx->dev_name2)) {
strcpy(sns_entity_name2, rk_aiq_uapi2_sysctl_getBindedSnsEntNmByVd(ctx->dev_name2));
printf("sns_entity_name2:%s\n", sns_entity_name2);
//sscanf(&sns_entity_name2[6], "%s", ctx->sns_name);
//printf("sns_name2:%s\n", ctx->sns_name);
has_dev2 = true;
}
rk_aiq_camgroup_instance_cfg_t camgroup_cfg;
memset(&camgroup_cfg, 0, sizeof(camgroup_cfg));
camgroup_cfg.sns_num = 1;
if (has_dev2)
camgroup_cfg.sns_num++;
camgroup_cfg.sns_ent_nm_array[0] = sns_entity_name;
if (has_dev2)
camgroup_cfg.sns_ent_nm_array[1] = sns_entity_name2;
camgroup_cfg.config_file_dir = ctx->iqpath;
camgroup_cfg.overlap_map_file = "srcOverlapMap.bin";
ctx->camgroup_ctx = rk_aiq_uapi2_camgroup_create(&camgroup_cfg);
if (!ctx->camgroup_ctx) {
printf("create camgroup ctx error !\n");
exit(1);
}
#ifdef CUSTOM_GROUP_AE_DEMO_TEST
rk_aiq_customeAe_cbs_t cbs = {
.pfn_ae_init = custom_ae_init,
.pfn_ae_run = custom_ae_run,
.pfn_ae_ctrl = custom_ae_ctrl,
.pfn_ae_exit = custom_ae_exit,
};
rk_aiq_uapi2_customAE_register((const rk_aiq_sys_ctx_t*)(ctx->camgroup_ctx), &cbs);
rk_aiq_uapi2_customAE_enable((const rk_aiq_sys_ctx_t*)(ctx->camgroup_ctx), true);
#endif
#ifdef CUSTOM_GROUP_AWB_DEMO_TEST
rk_aiq_customeAwb_cbs_t awb_cbs = {
.pfn_awb_init = custom_awb_init,
.pfn_awb_run = custom_awb_run,
.pfn_awb_ctrl= custom_awb_ctrl,
.pfn_awb_exit = custom_awb_exit,
};
rk_aiq_uapi2_customAWB_register((const rk_aiq_sys_ctx_t*)(ctx->camgroup_ctx), &awb_cbs);
rk_aiq_uapi2_customAWB_enable((const rk_aiq_sys_ctx_t*)(ctx->camgroup_ctx), true);
#endif
}
}
} else {
if (ctx->camGroup) {
printf("error! should specify iq path !\n");
exit(1);
}
#ifndef ANDROID
rk_aiq_uapi2_sysctl_preInit(sns_entity_name, RK_AIQ_WORKING_MODE_NORMAL, "ov5695_TongJu_CHT842-MD.xml");
ctx->aiq_ctx = rk_aiq_uapi2_sysctl_init(sns_entity_name, "/oem/etc/iqfiles", NULL, NULL);
#else
ctx->aiq_ctx = rk_aiq_uapi2_sysctl_init(sns_entity_name, "/data/etc/iqfiles", NULL, NULL);
#endif
}
if (ctx->aiq_ctx) {
printf("%s:-------- init mipi tx/rx -------------\n", get_sensor_name(ctx));
if (ctx->writeFileSync)
rk_aiq_uapi2_debug_captureRawYuvSync(ctx->aiq_ctx, CAPTURE_RAW_AND_YUV_SYNC);
#ifdef CUSTOM_AE_DEMO_TEST
//ae_reg.stAeExpFunc.pfn_ae_init = ae_init;
//ae_reg.stAeExpFunc.pfn_ae_run = ae_run;
//ae_reg.stAeExpFunc.pfn_ae_ctrl = ae_ctrl;
//ae_reg.stAeExpFunc.pfn_ae_exit = ae_exit;
//rk_aiq_AELibRegCallBack(ctx->aiq_ctx, &ae_reg, 0);
rk_aiq_customeAe_cbs_t cbs = {
.pfn_ae_init = custom_ae_init,
.pfn_ae_run = custom_ae_run,
.pfn_ae_ctrl = custom_ae_ctrl,
.pfn_ae_exit = custom_ae_exit,
};
rk_aiq_uapi2_customAE_register(ctx->aiq_ctx, &cbs);
rk_aiq_uapi2_customAE_enable(ctx->aiq_ctx, true);
#endif
#ifdef CUSTOM_AWB_DEMO_TEST
rk_aiq_customeAwb_cbs_t awb_cbs = {
.pfn_awb_init = custom_awb_init,
.pfn_awb_run = custom_awb_run,
.pfn_awb_ctrl = custom_awb_ctrl,
.pfn_awb_exit = custom_awb_exit,
};
rk_aiq_uapi2_customAWB_register(ctx->aiq_ctx, &awb_cbs);
rk_aiq_uapi2_customAWB_enable(ctx->aiq_ctx, true);
#endif
if (ctx->isOrp) {
rk_aiq_raw_prop_t prop;
if (strcmp(ctx->orpRawFmt, "BA81") == 0)
prop.format = RK_PIX_FMT_SBGGR8;
else if (strcmp(ctx->orpRawFmt, "GBRG") == 0)
prop.format = RK_PIX_FMT_SGBRG8;
else if (strcmp(ctx->orpRawFmt, "RGGB") == 0)
prop.format = RK_PIX_FMT_SRGGB8;
else if (strcmp(ctx->orpRawFmt, "GRBG") == 0)
prop.format = RK_PIX_FMT_SGRBG8;
else if (strcmp(ctx->orpRawFmt, "BG10") == 0)
prop.format = RK_PIX_FMT_SBGGR10;
else if (strcmp(ctx->orpRawFmt, "GB10") == 0)
prop.format = RK_PIX_FMT_SGBRG10;
else if (strcmp(ctx->orpRawFmt, "RG10") == 0)
prop.format = RK_PIX_FMT_SRGGB10;
else if (strcmp(ctx->orpRawFmt, "BA10") == 0)
prop.format = RK_PIX_FMT_SGRBG10;
else if (strcmp(ctx->orpRawFmt, "BG12") == 0)
prop.format = RK_PIX_FMT_SBGGR12;
else if (strcmp(ctx->orpRawFmt, "GB12") == 0)
prop.format = RK_PIX_FMT_SGBRG12;
else if (strcmp(ctx->orpRawFmt, "RG12") == 0)
prop.format = RK_PIX_FMT_SRGGB12;
else if (strcmp(ctx->orpRawFmt, "BA12") == 0)
prop.format = RK_PIX_FMT_SGRBG12;
else if (strcmp(ctx->orpRawFmt, "BG14") == 0)
prop.format = RK_PIX_FMT_SBGGR14;
else if (strcmp(ctx->orpRawFmt, "GB14") == 0)
prop.format = RK_PIX_FMT_SGBRG14;
else if (strcmp(ctx->orpRawFmt, "RG14") == 0)
prop.format = RK_PIX_FMT_SRGGB14;
else if (strcmp(ctx->orpRawFmt, "BA14") == 0)
prop.format = RK_PIX_FMT_SGRBG14;
else
prop.format = RK_PIX_FMT_SBGGR10;
prop.frame_width = ctx->orpRawW;
prop.frame_height = ctx->orpRawH;
prop.rawbuf_type = RK_AIQ_RAW_FILE;
rk_aiq_uapi2_sysctl_prepareRkRaw(ctx->aiq_ctx, prop);
}
/*
* rk_aiq_uapi_setFecEn(ctx->aiq_ctx, true);
* rk_aiq_uapi_setFecCorrectDirection(ctx->aiq_ctx, FEC_CORRECT_DIRECTION_Y);
*/
#ifdef TEST_MEMS_SENSOR_INTF
rk_aiq_mems_sensor_intf_t g_rkiio_aiq_api;
rk_aiq_uapi2_sysctl_regMemsSensorIntf(ctx->aiq_ctx, &g_rkiio_aiq_api);
#endif
#if 0
test_tuning_api(ctx);
#endif
XCamReturn ret = rk_aiq_uapi2_sysctl_prepare(ctx->aiq_ctx, ctx->width, ctx->height, work_mode);
if (ret != XCAM_RETURN_NO_ERROR)
ERR("%s:rk_aiq_uapi2_sysctl_prepare failed: %d\n", get_sensor_name(ctx), ret);
else {
ret = rk_aiq_uapi2_setMirrorFlip(ctx->aiq_ctx, false, false, 3);
// Ignore failure
if (ctx->isOrp) {
rk_aiq_uapi2_sysctl_registRkRawCb(ctx->aiq_ctx, release_buffer);
}
ret = rk_aiq_uapi2_sysctl_start(ctx->aiq_ctx );
init_device(ctx);
if (ctx->pponeframe)
init_device_pp_oneframe(ctx);
if (ctx->ctl_type == TEST_CTL_TYPE_DEFAULT) {
start_capturing(ctx);
}
if (ctx->pponeframe)
start_capturing_pp_oneframe(ctx);
printf("%s:-------- stream on mipi tx/rx -------------\n", get_sensor_name(ctx));
if (ctx->ctl_type != TEST_CTL_TYPE_DEFAULT) {
restart:
static int test_ctl_cnts = 0;
ctx->frame_count = 60;
start_capturing(ctx);
while ((ctx->frame_count-- > 0))
read_frame(ctx);
stop_capturing(ctx);
printf("+++++++ TEST SYSCTL COUNTS %d ++++++++++++ \n", test_ctl_cnts++);
printf("aiq stop .....\n");
rk_aiq_uapi2_sysctl_stop(ctx->aiq_ctx, false);
if (ctx->ctl_type == TEST_CTL_TYPE_REPEAT_INIT_PREPARE_START_STOP_DEINIT) {
printf("aiq deinit .....\n");
rk_aiq_uapi2_sysctl_deinit(ctx->aiq_ctx);
printf("aiq init .....\n");
if (work_mode == RK_AIQ_WORKING_MODE_NORMAL) {
ret = rk_aiq_uapi2_sysctl_preInit_scene(sns_entity_name, "normal", "day");
if (ctx->hdrmode == 2)
work_mode = RK_AIQ_WORKING_MODE_ISP_HDR2;
else if (ctx->hdrmode == 3)
work_mode = RK_AIQ_WORKING_MODE_ISP_HDR3;
} else {
ret = rk_aiq_uapi2_sysctl_preInit_scene(sns_entity_name, "hdr", "day");
work_mode = RK_AIQ_WORKING_MODE_NORMAL;
}
if (ret < 0)
ERR("%s: failed to set %s scene\n",
get_sensor_name(ctx),
work_mode == RK_AIQ_WORKING_MODE_NORMAL ? "normal" : "hdr");
ctx->aiq_ctx = rk_aiq_uapi2_sysctl_init(sns_entity_name, ctx->iqpath, NULL, NULL);
printf("aiq prepare .....\n");
XCamReturn ret = rk_aiq_uapi2_sysctl_prepare(ctx->aiq_ctx, ctx->width, ctx->height, work_mode);
} else if (ctx->ctl_type == TEST_CTL_TYPE_REPEAT_PREPARE_START_STOP) {
printf("aiq prepare .....\n");
XCamReturn ret = rk_aiq_uapi2_sysctl_prepare(ctx->aiq_ctx, ctx->width, ctx->height, work_mode);
} else if (ctx->ctl_type == TEST_CTL_TYPE_REPEAT_START_STOP) {
// do nothing
}
printf("aiq start .....\n");
ret = rk_aiq_uapi2_sysctl_start(ctx->aiq_ctx );
printf("aiq restart .....\n");
goto restart;
}
}
} else if (ctx->camgroup_ctx) {
// only do once for cam group
if (ctx->dev_using == 1) {
XCamReturn ret = rk_aiq_uapi2_camgroup_prepare(ctx->camgroup_ctx, work_mode);
if (ret != XCAM_RETURN_NO_ERROR)
ERR("%s:rk_aiq_uapi2_camgroup_prepare failed: %d\n", get_sensor_name(ctx), ret);
else {
ret = rk_aiq_uapi2_camgroup_start(ctx->camgroup_ctx);
}
}
init_device(ctx);
start_capturing(ctx);
}
}
else {
init_device(ctx);
if (ctx->pponeframe)
init_device_pp_oneframe(ctx);
start_capturing(ctx);
if (ctx->pponeframe)
start_capturing_pp_oneframe(ctx);
}
}
static void* others_thread(void* args) {
pthread_detach (pthread_self());
demo_context_t* ctx = (demo_context_t*) args;
rkisp_routine(ctx);
mainloop(ctx);
deinit(ctx);
return 0;
}
int main(int argc, char **argv)
{
#ifdef _WIN32
signal (SIGINT, signal_handle);
signal (SIGQUIT, signal_handle);
signal (SIGTERM, signal_handle);
#else
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGQUIT);
pthread_sigmask(SIG_BLOCK, &mask, NULL);
struct sigaction new_action, old_action;
new_action.sa_handler = signal_handle;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction (SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGINT, &new_action, NULL);
sigaction (SIGQUIT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGQUIT, &new_action, NULL);
sigaction (SIGTERM, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGTERM, &new_action, NULL);
#endif
demo_context_t main_ctx = {
.out_file = {'\0'},
.dev_name = {'\0'},
.dev_name2 = {'\0'},
.dev_name3 = {'\0'},
.dev_name4 = {'\0'},
.sns_name = {'\0'},
.dev_using = 1,
.width = 640,
.height = 480,
.format = V4L2_PIX_FMT_NV12,
.fd = -1,
.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.buffers = NULL,
.n_buffers = 0,
.frame_count = -1,
.fp = NULL,
.aiq_ctx = NULL,
.camgroup_ctx = NULL,
.vop = 0,
.rkaiq = 0,
.writeFile = 0,
.writeFileSync = 0,
.pponeframe = 0,
.hdrmode = 0,
.limit_range = 0,
.fd_pp_input = -1,
.fd_isp_mp = -1,
.buffers_mp = NULL,
.outputCnt = 3,
.skipCnt = 30,
.yuv_dir_path = {'\0'},
._is_yuv_dir_exist = false,
.capture_yuv_num = 0,
.is_capture_yuv = false,
.ctl_type = TEST_CTL_TYPE_DEFAULT,
.iqpath = {'\0'},
.orppath = {'\0'},
.orpRawW = 0,
.orpRawH = 0,
.orpRawFmt = {'\0'},
.isOrp = false,
.orpStop = false,
.orpStopped = false,
.camGroup = false,
};
demo_context_t second_ctx;
demo_context_t third_ctx;
demo_context_t fourth_ctx;
parse_args(argc, argv, &main_ctx);
#if ISPDEMO_ENABLE_DRM
if (main_ctx.vop) {
#if ISPDEMO_ENABLE_RGA
if (strlen(main_ctx.dev_name) && strlen(main_ctx.dev_name2)) {
if (display_init(720, 1280) < 0) {
printf("display_init failed\n");
}
} else {
#else
{
#endif
if (initDrmDsp() < 0) {
printf("initDrmDsp failed\n");
}
}
}
#endif
rkisp_routine(&main_ctx);
g_main_ctx = &main_ctx;
if(strlen(main_ctx.dev_name2)) {
pthread_t sec_tid;
second_ctx = main_ctx;
second_ctx.dev_using = 2;
g_second_ctx = &second_ctx;
pthread_create(&sec_tid, NULL, others_thread, &second_ctx);
}
if(strlen(main_ctx.dev_name3)) {
pthread_t thr_tid;
third_ctx = main_ctx;
third_ctx.dev_using = 3;
g_third_ctx = &third_ctx;
pthread_create(&thr_tid, NULL, others_thread, &third_ctx);
}
if(strlen(main_ctx.dev_name4)) {
pthread_t fou_tid;
fourth_ctx = main_ctx;
fourth_ctx.dev_using = 4;
g_fourth_ctx = &fourth_ctx;
pthread_create(&fou_tid, NULL, others_thread, &fourth_ctx);
}
#ifdef ENABLE_UAPI_TEST
pthread_t tid;
pthread_create(&tid, NULL, test_thread, &main_ctx);
#endif
if (main_ctx.isOrp) {
pthread_t tid_offline;
pthread_create(&tid_offline, NULL, test_offline_thread, &main_ctx);
}
//#define TEST_BLOCKED_STATS_FUNC
#ifdef TEST_BLOCKED_STATS_FUNC
pthread_t stats_tid;
pthread_create(&stats_tid, NULL, stats_thread, &main_ctx);
#endif
#ifdef CUSTOM_AF_DEMO_TEST
custom_af_run(main_ctx.aiq_ctx);
#endif
#ifdef ISPFEC_API
g_ispfec_cfg.in_width = main_ctx.width;
g_ispfec_cfg.in_height = main_ctx.height;
g_ispfec_cfg.out_width = main_ctx.width;
g_ispfec_cfg.out_height = main_ctx.height;
g_ispfec_cfg.in_fourcc = 0;
g_ispfec_cfg.out_fourcc = 0;
#if 1
g_ispfec_cfg.mesh_upd_mode = RK_ISPFEC_UPDATE_MESH_FROM_FILE;
strcpy(g_ispfec_cfg.u.mesh_file_path, "/etc/iqfiles/FEC_mesh_3840_2160_imx415_3.6mm/");
strcpy(g_ispfec_cfg.mesh_xint.mesh_file, "meshxi_level0.bin");
strcpy(g_ispfec_cfg.mesh_xfra.mesh_file, "meshxf_level0.bin");
strcpy(g_ispfec_cfg.mesh_yint.mesh_file, "meshyi_level0.bin");
strcpy(g_ispfec_cfg.mesh_yfra.mesh_file, "meshyf_level0.bin");
#else
g_ispfec_cfg.mesh_upd_mode = RK_ISPFEC_UPDATE_MESH_ONLINE;
g_ispfec_cfg.u.mesh_online.light_center[0] = 1956.3909119999998438;
g_ispfec_cfg.u.mesh_online.light_center[1] = 1140.6355200000000422;
g_ispfec_cfg.u.mesh_online.coeff[0] = -2819.4072493821618081;
g_ispfec_cfg.u.mesh_online.coeff[1] = 0.0000316126581792;
g_ispfec_cfg.u.mesh_online.coeff[2] = 0.0000000688410142;
g_ispfec_cfg.u.mesh_online.coeff[3] = -0.0000000000130686;
g_ispfec_cfg.u.mesh_online.correct_level = 250;
g_ispfec_cfg.u.mesh_online.direction = RK_ISPFEC_CORRECT_DIRECTION_XY;
g_ispfec_cfg.u.mesh_online.style = RK_ISPFEC_KEEP_ASPECT_RATIO_REDUCE_FOV;
#endif
init_ispfec_bufs(&g_ispfec_cfg);
g_ispfec_ctx = rk_ispfec_api_init(&g_ispfec_cfg);
#endif
pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
mainloop(&main_ctx);
if (main_ctx.isOrp) {
main_ctx.orpStop = true;
while (!main_ctx.orpStopped) {
printf("wait orp stopped ... \n");
usleep(500000);
}
}
deinit(&main_ctx);
#if ISPDEMO_ENABLE_DRM
#if ISPDEMO_ENABLE_RGA
if (strlen(main_ctx.dev_name) && strlen(main_ctx.dev_name2)) {
display_exit();
}
#endif
deInitDrmDsp();
#endif
return 0;
}