LicheeRV-Nano-Build
LicheeRV-Nano-Build copied to clipboard
sensor_test样例输出的yuv文件按照代码中定义的NV21格式打开,颜色错误
如题。
样例代码在SAMPLE_COMM_VI_IniToViCfg中, https://github.com/sipeed/LicheeRV-Nano-Build/blob/main/middleware/v2/sample/common/sample_common_vi.c#L1040 一行定义的图像格式为VI_PIXEL_FORMAT,即PIXEL_FORMAT_NV21。 但是运行sensor_test样例使用dump_yuv功能,或者根据该样例简化得到如下代码:
测试代码
#include <stdio.h>
#include <cvi_sys.h>
#include <sample_comm.h>
static SAMPLE_VI_CONFIG_S g_stViConfig;
static SAMPLE_INI_CFG_S g_stIniCfg;
static int sys_vi_init(void)
{
MMF_VERSION_S stVersion;
SAMPLE_INI_CFG_S stIniCfg;
SAMPLE_VI_CONFIG_S stViConfig;
PIC_SIZE_E enPicSize;
SIZE_S stSize;
CVI_S32 s32Ret = CVI_SUCCESS;
LOG_LEVEL_CONF_S log_conf;
CVI_SYS_GetVersion(&stVersion);
SAMPLE_PRT("MMF Version:%s\n", stVersion.version);
log_conf.enModId = CVI_ID_LOG;
log_conf.s32Level = CVI_DBG_INFO;
CVI_LOG_SetLevelConf(&log_conf);
// Get config from ini if found.
if (SAMPLE_COMM_VI_ParseIni(&stIniCfg)) {
SAMPLE_PRT("Parse complete\n");
}
//Set sensor number
CVI_VI_SetDevNum(stIniCfg.devNum);
/************************************************
* step1: Config VI
************************************************/
s32Ret = SAMPLE_COMM_VI_IniToViCfg(&stIniCfg, &stViConfig);
if (s32Ret != CVI_SUCCESS)
return s32Ret;
memcpy(&g_stViConfig, &stViConfig, sizeof(SAMPLE_VI_CONFIG_S));
memcpy(&g_stIniCfg, &stIniCfg, sizeof(SAMPLE_INI_CFG_S));
/************************************************
* step2: Get input size
************************************************/
s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stIniCfg.enSnsType[0], &enPicSize);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_LOG(CVI_DBG_ERR, "SAMPLE_COMM_VI_GetSizeBySensor failed with %#x\n", s32Ret);
return s32Ret;
}
s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_LOG(CVI_DBG_ERR, "SAMPLE_COMM_SYS_GetPicSize failed with %#x\n", s32Ret);
return s32Ret;
}
/************************************************
* step3: Init modules
************************************************/
s32Ret = SAMPLE_PLAT_SYS_INIT(stSize);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_LOG(CVI_DBG_ERR, "sys init failed. s32Ret: 0x%x !\n", s32Ret);
return s32Ret;
}
s32Ret = SAMPLE_PLAT_VI_INIT(&stViConfig);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_LOG(CVI_DBG_ERR, "vi init failed. s32Ret: 0x%x !\n", s32Ret);
return s32Ret;
}
return CVI_SUCCESS;
}
static void sys_vi_deinit(void)
{
SAMPLE_COMM_VI_DestroyIsp(&g_stViConfig);
SAMPLE_COMM_VI_DestroyVi(&g_stViConfig);
SAMPLE_COMM_SYS_Exit();
}
static CVI_S32 _vi_get_chn_frame(CVI_U8 chn)
{
VIDEO_FRAME_INFO_S stVideoFrame;
VI_CROP_INFO_S crop_info = {0};
if (CVI_VI_GetChnFrame(0, chn, &stVideoFrame, 3000) == 0) {
FILE *output;
size_t image_size = stVideoFrame.stVFrame.u32Length[0] + stVideoFrame.stVFrame.u32Length[1]
+ stVideoFrame.stVFrame.u32Length[2];
CVI_VOID *vir_addr;
CVI_U32 plane_offset, u32LumaSize, u32ChromaSize;
CVI_CHAR img_name[128] = {0, };
CVI_TRACE_LOG(CVI_DBG_WARN, "width: %d, height: %d, total_buf_length: %zu\n",
stVideoFrame.stVFrame.u32Width,
stVideoFrame.stVFrame.u32Height, image_size);
snprintf(img_name, sizeof(img_name), "sample_%d.yuv", chn);
output = fopen(img_name, "wb");
if (output == NULL) {
memset(img_name, 0x0, sizeof(img_name));
snprintf(img_name, sizeof(img_name), "/mnt/data/sample_%d.yuv", chn);
output = fopen(img_name, "wb");
if (output == NULL) {
CVI_VI_ReleaseChnFrame(0, chn, &stVideoFrame);
CVI_TRACE_LOG(CVI_DBG_ERR, "fopen fail\n");
return CVI_FAILURE;
}
}
u32LumaSize = stVideoFrame.stVFrame.u32Stride[0] * stVideoFrame.stVFrame.u32Height;
u32ChromaSize = stVideoFrame.stVFrame.u32Stride[1] * stVideoFrame.stVFrame.u32Height / 2;
CVI_VI_GetChnCrop(0, chn, &crop_info);
if (crop_info.bEnable) {
u32LumaSize = ALIGN((crop_info.stCropRect.u32Width * 8 + 7) >> 3, DEFAULT_ALIGN) *
ALIGN(crop_info.stCropRect.u32Height, 2);
u32ChromaSize = (ALIGN(((crop_info.stCropRect.u32Width >> 1) * 8 + 7) >> 3, DEFAULT_ALIGN) *
ALIGN(crop_info.stCropRect.u32Height, 2)) >> 1;
}
vir_addr = CVI_SYS_Mmap(stVideoFrame.stVFrame.u64PhyAddr[0], image_size);
CVI_SYS_IonInvalidateCache(stVideoFrame.stVFrame.u64PhyAddr[0], vir_addr, image_size);
plane_offset = 0;
for (int i = 0; i < 3; i++) {
if (stVideoFrame.stVFrame.u32Length[i] != 0) {
stVideoFrame.stVFrame.pu8VirAddr[i] = vir_addr + plane_offset;
plane_offset += stVideoFrame.stVFrame.u32Length[i];
CVI_TRACE_LOG(CVI_DBG_WARN,
"plane(%d): paddr(%#lld) vaddr(%p) stride(%d) length(%d)\n",
i, stVideoFrame.stVFrame.u64PhyAddr[i],
stVideoFrame.stVFrame.pu8VirAddr[i],
stVideoFrame.stVFrame.u32Stride[i],
stVideoFrame.stVFrame.u32Length[i]);
fwrite((void *)stVideoFrame.stVFrame.pu8VirAddr[i]
, (i == 0) ? u32LumaSize : u32ChromaSize, 1, output);
}
}
CVI_SYS_Munmap(vir_addr, image_size);
if (CVI_VI_ReleaseChnFrame(0, chn, &stVideoFrame) != 0)
CVI_TRACE_LOG(CVI_DBG_ERR, "CVI_VI_ReleaseChnFrame NG\n");
fclose(output);
return CVI_SUCCESS;
}
CVI_TRACE_LOG(CVI_DBG_ERR, "CVI_VI_GetChnFrame NG\n");
return CVI_FAILURE;
}
static CVI_S32 sensor_dump_yuv(void)
{
CVI_S32 loop = 0;
CVI_U32 ok = 0, ng = 0;
CVI_U8 chn = 0;
int tmp;
struct timespec start, end;
chn = 0;
loop = 5;
while (loop > 0) {
if (_vi_get_chn_frame(chn) == CVI_SUCCESS) {
++ok;
} else
++ng;
//sleep(1);
if (loop != 11111)
loop--;
}
CVI_TRACE_LOG(CVI_DBG_WARN, "VI GetChnFrame OK(%d) NG(%d)\n", ok, ng);
CVI_TRACE_LOG(CVI_DBG_WARN, "Dump VI yuv TEST-PASS\n");
return CVI_SUCCESS;
}
int main() {
sys_vi_init();
sensor_dump_yuv();
sys_vi_deinit();
return 0;
}
实际输出的图像使用NV21打开,颜色错误,使用NV12打开的颜色与实际更接近。 硬件为LicheeRV Nano 量产版本,软件为当前git最新版本。