505 lines
16 KiB
C
Executable File
505 lines
16 KiB
C
Executable File
/*
|
|
* Copyright (c) XMEDIA. All rights reserved.
|
|
*/
|
|
#include <sys/mman.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <sys/ioctl.h>
|
|
#include <errno.h>
|
|
|
|
#include "xmedia_vi.h"
|
|
#include "xmedia_mmz.h"
|
|
#include "xmedia_video_common.h"
|
|
|
|
#define MAX_FRAME_CNT 100
|
|
#define MAX_FRAME_WIDTH 3840
|
|
|
|
#define MAX_WAIT_TIME 1000 // 获取帧最长等待时间,单位ms
|
|
|
|
#define RAW_DUMP_DEPTH 2
|
|
|
|
#define FILE_NAME_LEN 256
|
|
|
|
#define r_printf(fmt, ...) \
|
|
do { \
|
|
printf("\e[31m\e[1m [%s]-%d: " fmt "\e[0m", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
|
} while (0)
|
|
|
|
xmedia_void vi_bayer_dump_usage(xmedia_void)
|
|
{
|
|
printf("\n"
|
|
"***************************************************************\n"
|
|
"Usage: ./vi_bayer_dump [pipe] [frame_cnt] [ratio_show]\n"
|
|
"pipe: \n"
|
|
" 0 ~ 7: Vi pipe 0 ~ 7, default is 0\n"
|
|
"frame_cnt: \n"
|
|
" The count of frame to be dump, default is 1\n"
|
|
"ratio_show: \n"
|
|
" Whether the file name of raw show ratio info, default is 0\n"
|
|
"e.g: ./vi_bayer_dump 0 1 1\n"
|
|
"***************************************************************\n"
|
|
"\n");
|
|
exit(1);
|
|
}
|
|
|
|
xmedia_s32 get_dump_pipe(xmedia_s32 pipe, xmedia_vi_dev_bind_pipe_attr *dev_bind_pipe)
|
|
{
|
|
xmedia_s32 ret;
|
|
xmedia_s32 dev;
|
|
xmedia_s32 i, j;
|
|
xmedia_bool is_get_dev = XMEDIA_FALSE;
|
|
xmedia_vi_grp_config grp_config;
|
|
xmedia_bool is_wdr_pipe = XMEDIA_FALSE;
|
|
xmedia_vi_dev_bind_pipe_attr dev_bind_pipe_tmp;
|
|
|
|
for (i = 0; i < VI_MAX_DEV_NUM; i++) {
|
|
ret = xmedia_vi_get_pipe_by_dev(i, &dev_bind_pipe_tmp);
|
|
if (ret == XMEDIA_SUCCESS) {
|
|
for (j = 0; j < dev_bind_pipe_tmp.pipe_num; j++) {
|
|
if (pipe == dev_bind_pipe_tmp.pipe_id[j]) {
|
|
dev = i;
|
|
is_get_dev = XMEDIA_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (is_get_dev == XMEDIA_FALSE) {
|
|
r_printf("pipe %d get bind dev failed\n", pipe);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
memset(dev_bind_pipe, 0, sizeof(xmedia_vi_dev_bind_pipe_attr));
|
|
|
|
ret = xmedia_vi_get_pipe_by_dev(dev, dev_bind_pipe);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
r_printf("xmedia_vi_get_pipe_by_dev failed with 0x%x\n", ret);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < VI_MAX_GRP_NUM; i++) {
|
|
ret = xmedia_vi_get_grp_config(i, &grp_config);
|
|
if (ret == XMEDIA_SUCCESS) {
|
|
if (grp_config.grp_type == XMEDIA_VI_GRP_TYPE_WDR) {
|
|
for (j = 0; j < VI_MAX_WDR_NUM; j++) {
|
|
if (grp_config.wdr_grp_config.pipe_id[j] == pipe) {
|
|
is_wdr_pipe = XMEDIA_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (is_wdr_pipe == XMEDIA_FALSE) {
|
|
dev_bind_pipe->pipe_num = 1;
|
|
dev_bind_pipe->pipe_id[0] = pipe;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_char *compress_mode_to_string(xmedia_video_compress_mode compress_mode)
|
|
{
|
|
if (compress_mode == XMEDIA_VIDEO_COMPRESS_MODE_NONE) {
|
|
return "cmp_none";
|
|
} else if (compress_mode == XMEDIA_VIDEO_COMPRESS_MODE_LINE) {
|
|
return "cmp_line";
|
|
} else if (compress_mode == XMEDIA_VIDEO_COMPRESS_MODE_SEG) {
|
|
return "cmp_seg";
|
|
} else {
|
|
return "cmp_xxx";
|
|
}
|
|
}
|
|
|
|
xmedia_u32 data_width_to_num(xmedia_video_data_width data_width)
|
|
{
|
|
if (data_width == XMEDIA_VIDEO_DATA_WIDTH_8) {
|
|
return 8;
|
|
} else if (data_width == XMEDIA_VIDEO_DATA_WIDTH_10) {
|
|
return 10;
|
|
} else if (data_width == XMEDIA_VIDEO_DATA_WIDTH_12) {
|
|
return 12;
|
|
} else if (data_width == XMEDIA_VIDEO_DATA_WIDTH_14) {
|
|
return 14;
|
|
} else if (data_width == XMEDIA_VIDEO_DATA_WIDTH_16) {
|
|
return 16;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
xmedia_s32 save_uncompress_raw_to_file(xmedia_video_frame *frame, FILE *fd)
|
|
{
|
|
xmedia_s32 i;
|
|
xmedia_u32 row;
|
|
xmedia_u32 stride;
|
|
xmedia_u64 phy_addr, size;
|
|
xmedia_u8 *data = XMEDIA_NULL;
|
|
xmedia_u8 *data_tmp = XMEDIA_NULL;
|
|
xmedia_u8 *usr_page_addr = XMEDIA_NULL;
|
|
xmedia_u16 *buf_tmp = XMEDIA_NULL;
|
|
xmedia_u32 tmp;
|
|
xmedia_u64 value;
|
|
xmedia_u32 out_cnt;
|
|
|
|
stride = frame->stride.y_stride;
|
|
|
|
size = stride * frame->height;
|
|
|
|
phy_addr = frame->addr.y_phy_addr;
|
|
|
|
usr_page_addr = xmedia_mmz_map(phy_addr, size, XMEDIA_FALSE);
|
|
if (usr_page_addr == XMEDIA_NULL) {
|
|
r_printf("mmz map phy 0x%llx size %llu failed\n", phy_addr, size);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
if (frame->bit_width != XMEDIA_VIDEO_DATA_WIDTH_8 && frame->bit_width != XMEDIA_VIDEO_DATA_WIDTH_16) {
|
|
buf_tmp = (xmedia_u16 *)malloc(frame->width * 2); // 文件非紧凑排布,10,12,14bits不超两倍
|
|
if (buf_tmp == XMEDIA_NULL) {
|
|
r_printf("malloc failed\n");
|
|
xmedia_mmz_unmap(usr_page_addr);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
}
|
|
|
|
data = usr_page_addr;
|
|
|
|
printf("saving Y............\n");
|
|
|
|
for (row = 0; row < frame->height; row++) {
|
|
out_cnt = 0;
|
|
if (frame->bit_width == XMEDIA_VIDEO_DATA_WIDTH_8) {
|
|
fwrite(data, frame->width, 1, fd);
|
|
} else if (frame->bit_width == XMEDIA_VIDEO_DATA_WIDTH_16) {
|
|
fwrite(data, frame->width, 2, fd);
|
|
} else if (frame->bit_width == XMEDIA_VIDEO_DATA_WIDTH_10) {
|
|
// 4 pixels consist of 5 bytes
|
|
tmp = frame->width / 4;
|
|
for (i = 0; i < tmp; i++) {
|
|
// byte4 byte3 byte2 byte1 byte0
|
|
data_tmp = data + 5 * i;
|
|
value = data_tmp[0] + ((xmedia_u32)data_tmp[1] << 8) + ((xmedia_u32)data_tmp[2] << 16) +
|
|
((xmedia_u32)data_tmp[3] << 24) + ((xmedia_u64)data_tmp[4] << 32);
|
|
buf_tmp[out_cnt++] = value & 0x3ff;
|
|
buf_tmp[out_cnt++] = (value >> 10) & 0x3ff;
|
|
buf_tmp[out_cnt++] = (value >> 20) & 0x3ff;
|
|
buf_tmp[out_cnt++] = (value >> 30) & 0x3ff;
|
|
}
|
|
fwrite(buf_tmp, frame->width, 2, fd);
|
|
} else if (frame->bit_width == XMEDIA_VIDEO_DATA_WIDTH_12) {
|
|
// 2 pixels consist of 3 bytes
|
|
tmp = frame->width / 2;
|
|
for (i = 0; i < tmp; i++) {
|
|
// byte2 byte1 byte0
|
|
data_tmp = data + 3 * i;
|
|
value = data_tmp[0] + ((xmedia_u32)data_tmp[1] << 8) + ((xmedia_u32)data_tmp[2] << 16);
|
|
buf_tmp[out_cnt++] = value & 0xfff;
|
|
buf_tmp[out_cnt++] = (value >> 12) & 0xfff;
|
|
}
|
|
fwrite(buf_tmp, frame->width, 2, fd);
|
|
} else if (frame->bit_width == XMEDIA_VIDEO_DATA_WIDTH_14) {
|
|
// 4 pixels consist of 7 bytes
|
|
tmp = frame->width / 4;
|
|
for (i = 0; i < tmp; i++) {
|
|
// byte6 byte5 byte4 byte3 byte2 byte1 byte0
|
|
data_tmp = data + 7 * i;
|
|
value = data_tmp[0] + ((xmedia_u32)data_tmp[1] << 8) + ((xmedia_u32)data_tmp[2] << 16) +
|
|
((xmedia_u32)data_tmp[3] << 24) + ((xmedia_u64)data_tmp[4] << 32) +
|
|
((xmedia_u64)data_tmp[5] << 40) + ((xmedia_u64)data_tmp[6] << 48);
|
|
buf_tmp[out_cnt++] = value & 0x3fff;
|
|
buf_tmp[out_cnt++] = (value >> 14) & 0x3fff;
|
|
buf_tmp[out_cnt++] = (value >> 28) & 0x3fff;
|
|
buf_tmp[out_cnt++] = (value >> 42) & 0x3fff;
|
|
}
|
|
fwrite(buf_tmp, frame->width, 2, fd);
|
|
}
|
|
data += frame->stride.y_stride;
|
|
}
|
|
|
|
if (frame->bit_width != XMEDIA_VIDEO_DATA_WIDTH_8 && frame->bit_width != XMEDIA_VIDEO_DATA_WIDTH_16) {
|
|
free(buf_tmp);
|
|
}
|
|
|
|
xmedia_mmz_unmap(usr_page_addr);
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 save_compress_raw_to_file(xmedia_video_frame *frame, FILE *fd)
|
|
{
|
|
// todo
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 save_raw_to_file(xmedia_video_frame *frame, FILE *fd)
|
|
{
|
|
if (frame->compress_mode == XMEDIA_VIDEO_COMPRESS_MODE_NONE) {
|
|
return save_uncompress_raw_to_file(frame, fd);
|
|
} else {
|
|
return save_compress_raw_to_file(frame, fd);
|
|
}
|
|
}
|
|
|
|
xmedia_s32 dump_linear_bayer(xmedia_s32 pipe, xmedia_u32 cnt, xmedia_u32 ratio_show)
|
|
{
|
|
xmedia_s32 i, j;
|
|
xmedia_s32 ret;
|
|
FILE *fd = NULL;
|
|
xmedia_char file_name[FILE_NAME_LEN] = { 0 };
|
|
xmedia_video_frame_info *frame_info = XMEDIA_NULL;
|
|
|
|
frame_info = malloc(sizeof(xmedia_video_frame_info) * cnt);
|
|
if (frame_info == XMEDIA_NULL) {
|
|
r_printf("malloc failed\n");
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
ret = xmedia_vi_acquire_pipe_frame(pipe, &frame_info[i], MAX_WAIT_TIME);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
r_printf("linear: get pipe %d frame failed with 0x%x", pipe, ret);
|
|
r_printf("only get %d frames\n", i);
|
|
break;
|
|
}
|
|
|
|
printf("linear: get pipe %d frame %d ok\n", pipe, i);
|
|
}
|
|
|
|
if (i == 0) {
|
|
free(frame_info);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
// make file name
|
|
if (ratio_show == 0) {
|
|
snprintf(file_name, FILE_NAME_LEN, "./vi_pipe_%d_%ux%u_%d_%dbits_%s_%d.raw", pipe, frame_info[0].frame.width,
|
|
frame_info[0].frame.height, cnt, data_width_to_num(frame_info[0].frame.bit_width),
|
|
compress_mode_to_string(frame_info[0].frame.compress_mode), ratio_show);
|
|
} else {
|
|
// todo
|
|
snprintf(file_name, FILE_NAME_LEN, "./vi_pipe_%d_%ux%u_%d_%dbits_%s_%d.raw", pipe, frame_info[0].frame.width,
|
|
frame_info[0].frame.height, cnt, data_width_to_num(frame_info[0].frame.bit_width),
|
|
compress_mode_to_string(frame_info[0].frame.compress_mode), ratio_show);
|
|
}
|
|
|
|
fd = fopen(file_name, "wb");
|
|
if (fd == NULL) {
|
|
r_printf("open file faied\n");
|
|
goto failed;
|
|
}
|
|
|
|
// todo,压缩文件,先保存压缩param
|
|
|
|
for (j = 0; j < i; j++) {
|
|
printf("frame %d save start\n", j);
|
|
save_raw_to_file(&frame_info[j].frame, fd);
|
|
printf("frame %d save completed\n", j);
|
|
xmedia_vi_release_pipe_frame(pipe, &frame_info[j]);
|
|
}
|
|
|
|
fclose(fd);
|
|
|
|
free(frame_info);
|
|
|
|
return XMEDIA_SUCCESS;
|
|
|
|
failed:
|
|
for (j = 0; j < i; j++) {
|
|
xmedia_vi_release_pipe_frame(pipe, &frame_info[j]);
|
|
}
|
|
|
|
free(frame_info);
|
|
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
xmedia_s32 dump_wdr_bayer(xmedia_vi_dev_bind_pipe_attr *bind_attr, xmedia_u32 cnt, xmedia_u32 ratio_show)
|
|
{
|
|
xmedia_s32 i, j, k;
|
|
xmedia_s32 ret;
|
|
FILE *fd = NULL;
|
|
xmedia_u32 frame_cnt = 0;
|
|
xmedia_char file_name[FILE_NAME_LEN] = { 0 };
|
|
xmedia_video_frame_info *frame_info[VI_MAX_WDR_FRAME_NUM] = { XMEDIA_NULL };
|
|
|
|
for (i = 0; i < bind_attr->pipe_num; i++) {
|
|
frame_info[i] = malloc(sizeof(xmedia_video_frame_info) * cnt);
|
|
if (frame_info[i] == XMEDIA_NULL) {
|
|
r_printf("pipe %d malloc frame info failed\n", bind_attr->pipe_id[i]);
|
|
for (j = 0; j < i; j++) {
|
|
free(frame_info[j]);
|
|
}
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
for (j = 0; j < bind_attr->pipe_num; j++) {
|
|
ret = xmedia_vi_acquire_pipe_frame(bind_attr->pipe_id[j], &frame_info[j][i], MAX_WAIT_TIME);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
r_printf("wdr: get pipe %d frame failed with 0x%x", bind_attr->pipe_id[j], ret);
|
|
r_printf("only get %d frames\n", i);
|
|
frame_cnt = i;
|
|
for (k = 0; k < bind_attr->pipe_num; k++) {
|
|
xmedia_vi_release_pipe_frame(bind_attr->pipe_id[k], &frame_info[k][i]);
|
|
goto save_frame;
|
|
}
|
|
} else {
|
|
printf("wdr: get pipe %d frame %d ok\n", bind_attr->pipe_id[j], i);
|
|
}
|
|
}
|
|
}
|
|
|
|
frame_cnt = i;
|
|
|
|
// make file name
|
|
if (ratio_show == 0) {
|
|
snprintf(file_name, FILE_NAME_LEN, "./vi_pipe_%d_%ux%u_%d_%dbits_%s_%d_wdr.raw", bind_attr->pipe_id[0],
|
|
frame_info[0][0].frame.width, frame_info[0][0].frame.height, cnt * bind_attr->pipe_num,
|
|
data_width_to_num(frame_info[0][0].frame.bit_width),
|
|
compress_mode_to_string(frame_info[0][0].frame.compress_mode), ratio_show);
|
|
} else {
|
|
// todo
|
|
snprintf(file_name, FILE_NAME_LEN, "./vi_pipe_%d_%ux%u_%d_%dbits_%s_%d_wdr.raw", bind_attr->pipe_id[0],
|
|
frame_info[0][0].frame.width, frame_info[0][0].frame.height, cnt * bind_attr->pipe_num,
|
|
data_width_to_num(frame_info[0][0].frame.bit_width),
|
|
compress_mode_to_string(frame_info[0][0].frame.compress_mode), ratio_show);
|
|
}
|
|
|
|
fd = fopen(file_name, "wb");
|
|
if (fd == NULL) {
|
|
r_printf("open file faied\n");
|
|
goto end;
|
|
}
|
|
|
|
save_frame:
|
|
if (frame_cnt == 0) {
|
|
for (i = 0; i < bind_attr->pipe_num; i++) {
|
|
free(frame_info[i]);
|
|
}
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
for (i = 0; i < frame_cnt; i++) {
|
|
for (j = 0; j < bind_attr->pipe_num; j++) {
|
|
printf("pipe %d frame %d save start\n", bind_attr->pipe_id[j], i);
|
|
save_raw_to_file(&frame_info[j][i].frame, fd);
|
|
printf("pipe %d frame %d save completed\n", bind_attr->pipe_id[j], i);
|
|
}
|
|
}
|
|
|
|
end:
|
|
if (fd != XMEDIA_NULL) {
|
|
fclose(fd);
|
|
}
|
|
|
|
for (i = 0; i < frame_cnt; i++) {
|
|
for (j = 0; j < bind_attr->pipe_num; j++) {
|
|
xmedia_vi_release_pipe_frame(bind_attr->pipe_id[j], &frame_info[j][i]);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < bind_attr->pipe_num; i++) {
|
|
free(frame_info[i]);
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 main(xmedia_s32 argc, xmedia_char *argv[])
|
|
{
|
|
xmedia_s32 i;
|
|
xmedia_s32 ret;
|
|
xmedia_s32 pipe = 0;
|
|
xmedia_u32 frame_cnt = 1;
|
|
xmedia_u32 ratio_show = 0;
|
|
xmedia_vi_dev_bind_pipe_attr dev_bind_pipe;
|
|
xmedia_vi_frame_dump_attr dump_attr;
|
|
xmedia_vi_frame_dump_attr dump_attr_tmp;
|
|
|
|
printf("\nNOTIC: this tool only can be used for TESTING !!!\n");
|
|
printf("\n To see more usage, please enter: ./vi_bayer_dump -h\n\n");
|
|
|
|
if (argc > 1) {
|
|
if (strncmp(argv[1], "-h", 2) == 0) {
|
|
vi_bayer_dump_usage();
|
|
exit(XMEDIA_SUCCESS);
|
|
} else {
|
|
pipe = atoi(argv[1]); // pipe
|
|
}
|
|
}
|
|
|
|
if (argc > 2) {
|
|
frame_cnt = atoi(argv[2]); // the frame number
|
|
if (frame_cnt < 1 || frame_cnt > MAX_FRAME_CNT) {
|
|
r_printf("invalid frame cnt %u, range [1, %d]\n", frame_cnt, MAX_FRAME_CNT);
|
|
exit(XMEDIA_FAILURE);
|
|
}
|
|
}
|
|
|
|
if (argc > 3) {
|
|
if (atoi(argv[3]) > 0) {
|
|
ratio_show = 1;
|
|
} else {
|
|
ratio_show = 0;
|
|
}
|
|
}
|
|
|
|
ret = xmedia_vi_init();
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
r_printf("vi init failed !\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = get_dump_pipe(pipe, &dev_bind_pipe);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
xmedia_vi_exit();
|
|
r_printf("get_dump_pipe failed !\n");
|
|
return ret;
|
|
}
|
|
|
|
for (i = 0; i < dev_bind_pipe.pipe_num; i++) {
|
|
ret = xmedia_vi_get_pipe_frame_dump_attr(dev_bind_pipe.pipe_id[i], &dump_attr_tmp);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
xmedia_vi_exit();
|
|
r_printf("get pipe %d dump attr failed with 0x%x\n", dev_bind_pipe.pipe_id[i], ret);
|
|
return ret;
|
|
}
|
|
|
|
dump_attr.enable = XMEDIA_TRUE;
|
|
dump_attr.depth = RAW_DUMP_DEPTH;
|
|
ret = xmedia_vi_set_pipe_frame_dump_attr(dev_bind_pipe.pipe_id[i], &dump_attr);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
r_printf("set pipe %d dump attr failed with 0x%x\n", dev_bind_pipe.pipe_id[i], ret);
|
|
xmedia_vi_exit();
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
if (dev_bind_pipe.pipe_num == 1) {
|
|
dump_linear_bayer(pipe, frame_cnt, ratio_show);
|
|
} else {
|
|
dump_wdr_bayer(&dev_bind_pipe, frame_cnt, ratio_show);
|
|
}
|
|
|
|
for (i = 0; i < dev_bind_pipe.pipe_num; i++) {
|
|
ret = xmedia_vi_set_pipe_frame_dump_attr(dev_bind_pipe.pipe_id[i], &dump_attr_tmp);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
r_printf("set pipe %d dump attr failed with 0x%x\n", dev_bind_pipe.pipe_id[i], ret);
|
|
xmedia_vi_exit();
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
xmedia_vi_exit();
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|