Files
gk-sdk/source/gmp/usr/dump_tools/vi_chn_dump.c
T

447 lines
14 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_vb.h"
#include "xmedia_vgs.h"
#include "xmedia_video_common.h"
#define MAX_FRAME_CNT 100
#define MAX_FRAME_WIDTH 3840
#define MAX_WAIT_TIME 1000 // 获取帧最长等待时间,单位ms
#define YUV_DUMP_DEPTH 2
#define FILE_NAME_LEN 256
#define PIXEL_NAME_LEN 10
#define VIDEO_FRAME_LEN 20
#define r_printf(fmt, ...) \
do { \
printf("\e[31m\e[1m [%s]-%d: " fmt "\e[0m", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while (0)
xmedia_void vi_chn_dump_usage(xmedia_void)
{
printf("\n"
"***************************************************************\n"
"Usage: ./vi_chn_dump [pipe] [chn] [frame_cnt]\n"
"pipe: \n"
" 0 ~ 7: Vi pipe 0 ~ 7\n"
"chn: \n"
" 0: Vi chn\n"
"frame_cnt: \n"
" The count of frame to be dump\n"
"e.g: ./vi_chn_dump 0 0 1\n"
"***************************************************************\n"
"\n");
exit(1);
}
xmedia_s32 make_yuv_file_name(xmedia_s32 pipe, xmedia_s32 chn, xmedia_u32 cnt, xmedia_char *file_name)
{
xmedia_s32 ret;
xmedia_char pixel_format[PIXEL_NAME_LEN];
xmedia_char video_format[VIDEO_FRAME_LEN];
xmedia_video_frame_info frame_info;
ret = xmedia_vi_acquire_chn_frame(pipe, chn, &frame_info, MAX_WAIT_TIME);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d get chn frame failed with 0x%x\n", pipe, chn, ret);
return ret;
}
switch (frame_info.frame.pixel_fmt) {
case XMEDIA_VIDEO_PIXEL_FMT_YUV_SEMIPLANAR_420:
case XMEDIA_VIDEO_PIXEL_FMT_YVU_SEMIPLANAR_420:
snprintf(pixel_format, PIXEL_NAME_LEN, "p420");
break;
case XMEDIA_VIDEO_PIXEL_FMT_YUV_SEMIPLANAR_422:
case XMEDIA_VIDEO_PIXEL_FMT_YVU_SEMIPLANAR_422:
snprintf(pixel_format, PIXEL_NAME_LEN, "p422");
break;
case XMEDIA_VIDEO_PIXEL_FMT_YUV_400:
snprintf(pixel_format, PIXEL_NAME_LEN, "p400");
break;
default:
snprintf(pixel_format, PIXEL_NAME_LEN, "--");
break;
}
switch (frame_info.frame.video_fmt) {
case XMEDIA_VIDEO_FMT_LINEAR:
snprintf(video_format, VIDEO_FRAME_LEN, "linear");
break;
case XMEDIA_VIDEO_FMT_TILE_32x4:
snprintf(video_format, VIDEO_FRAME_LEN, "tile_32x4");
break;
case XMEDIA_VIDEO_FMT_TILE_64x4:
snprintf(video_format, VIDEO_FRAME_LEN, "tile_64x4");
break;
default:
snprintf(video_format, VIDEO_FRAME_LEN, "--");
break;
}
snprintf(file_name, FILE_NAME_LEN, "./vi_pipe%d_chn%d_%ux%u_%s_%s_%u.yuv", pipe, chn, frame_info.frame.width,
frame_info.frame.height, pixel_format, video_format, cnt);
ret = xmedia_vi_release_chn_frame(pipe, chn, &frame_info);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d release chn frame failed with 0x%x\n", pipe, chn, ret);
return ret;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 save_yuv_8bit_to_file(xmedia_video_frame *frame, FILE *fd)
{
xmedia_u32 width, height, size;
xmedia_u32 c_height;
xmedia_u64 phy_addr;
xmedia_char *usr_page_addr = XMEDIA_NULL;
xmedia_char *y_virt = XMEDIA_NULL;
xmedia_char *c_virt = XMEDIA_NULL;
xmedia_char *mem_offset = XMEDIA_NULL;
xmedia_char buf_tmp[MAX_FRAME_WIDTH];
if (frame->pixel_fmt == XMEDIA_VIDEO_PIXEL_FMT_YUV_SEMIPLANAR_420 ||
frame->pixel_fmt == XMEDIA_VIDEO_PIXEL_FMT_YVU_SEMIPLANAR_420) {
size = frame->stride.y_stride * frame->height * 3 / 2;
c_height = frame->height / 2;
} else if (frame->pixel_fmt == XMEDIA_VIDEO_PIXEL_FMT_YUV_SEMIPLANAR_422 ||
frame->pixel_fmt == XMEDIA_VIDEO_PIXEL_FMT_YVU_SEMIPLANAR_422) {
size = frame->stride.y_stride * frame->height * 2;
c_height = frame->height;
} else if (frame->pixel_fmt == XMEDIA_VIDEO_PIXEL_FMT_YUV_400) {
size = frame->width * frame->height;
c_height = 0;
} else {
r_printf("unknown pixel format %d\n", frame->pixel_fmt);
return XMEDIA_FAILURE;
}
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 %u failed\n", phy_addr, size);
return XMEDIA_FAILURE;
}
y_virt = usr_page_addr;
c_virt = y_virt + frame->stride.y_stride * frame->height;
printf("saving......Y......\n");
for (height = 0; height < frame->height; height++) {
mem_offset = y_virt + frame->stride.y_stride * height;
fwrite(mem_offset, frame->width, 1, fd);
}
if (frame->pixel_fmt != XMEDIA_VIDEO_PIXEL_FMT_YUV_400) {
printf("saving......U......\n");
for (height = 0; height < c_height; height++) {
mem_offset = c_virt + frame->stride.c_stride * height;
mem_offset += 1;
for (width = 0; width < frame->width / 2; width++) {
buf_tmp[width] = *mem_offset;
mem_offset += 2;
}
fwrite(buf_tmp, frame->width / 2, 1, fd);
}
printf("saving......V......\n");
for (height = 0; height < c_height; height++) {
mem_offset = c_virt + frame->stride.c_stride * height;
for (width = 0; width < frame->width / 2; width++) {
buf_tmp[width] = *mem_offset;
mem_offset += 2;
}
fwrite(buf_tmp, frame->width / 2, 1, fd);
}
}
printf("done %llu\n", frame->pts);
xmedia_mmz_unmap(usr_page_addr);
return XMEDIA_SUCCESS;
}
xmedia_s32 submit_vgs_to_transform(xmedia_s32 pipe, xmedia_s32 chn, xmedia_video_frame_info *in_frame, FILE *fd)
{
xmedia_s32 ret;
xmedia_vb_base_info base_info;
xmedia_vb_cal_cfg cal_cfg;
xmedia_vb_pool_config pool_config = {0};
xmedia_u32 pool_id;
xmedia_handle vb_handle;
xmedia_u64 phy_addr;
xmedia_s32 handle;
xmedia_vgs_frame_info task_info;
xmedia_video_rotation rot = XMEDIA_VIDEO_ROTATION_0;
xmedia_video_frame_info out_frame;
xmedia_vb_config vb_config = {0};
base_info.align = 0;
base_info.bit_width = in_frame->frame.bit_width;
base_info.cmp_mode = XMEDIA_VIDEO_COMPRESS_MODE_NONE;
base_info.width = in_frame->frame.width;
base_info.height = in_frame->frame.height;
base_info.pixel_fmt = in_frame->frame.pixel_fmt;
base_info.video_fmt = XMEDIA_VIDEO_FMT_LINEAR;
ret = xmedia_vb_get_buffer_config(&base_info, &cal_cfg);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d get buffer config failed with 0x%x\n", pipe, chn, ret);
return ret;
}
vb_config.max_pool_cnt = 1;
vb_config.common_pool[0].block_size = cal_cfg.vb_size;
vb_config.common_pool[0].block_cnt = 1;
ret = xmedia_vb_init(&vb_config);
if (ret != XMEDIA_SUCCESS) {
r_printf("vb init failed\n");
return ret;
}
pool_config.block_size = cal_cfg.vb_size;
pool_config.block_cnt = 1;
pool_config.map_mode = XMEDIA_VB_MAP_MODE_NONE;
pool_id = xmedia_vb_create_pool(&pool_config);
if (pool_id == VB_INVALID_POOLID) {
r_printf("pipe %d chn %d create pool failed\n", pipe, chn);
xmedia_vb_exit();
return XMEDIA_FAILURE;
}
vb_handle = xmedia_vb_get_block(pool_id, cal_cfg.vb_size, XMEDIA_NULL);
if (vb_handle == VB_INVALID_HANDLE) {
r_printf("pipe %d chn %d get block failed\n", pipe, chn);
xmedia_vb_exit();
return XMEDIA_FAILURE;
}
phy_addr = xmedia_vb_handle_to_phy_addr(vb_handle);
memset(&out_frame, 0, sizeof(xmedia_video_frame_info));
out_frame.pool_id = pool_id;
out_frame.mod_id = MOD_ID_VI;
out_frame.frame.addr.y_phy_addr = phy_addr;
out_frame.frame.addr.c_phy_addr = phy_addr + cal_cfg.main_y_size;
out_frame.frame.width = in_frame->frame.width;
out_frame.frame.height = in_frame->frame.height;
out_frame.frame.stride.y_stride = cal_cfg.main_stride;
out_frame.frame.stride.c_stride = cal_cfg.main_stride;
out_frame.frame.compress_mode = XMEDIA_VIDEO_COMPRESS_MODE_NONE;
out_frame.frame.pixel_fmt = in_frame->frame.pixel_fmt;
out_frame.frame.video_fmt = XMEDIA_VIDEO_FMT_LINEAR;
out_frame.frame.dynamic_range = in_frame->frame.dynamic_range;
out_frame.frame.pts = in_frame->frame.pts;
out_frame.frame.index = in_frame->frame.index;
ret = xmedia_vgs_init();
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d init failed\n", pipe, chn);
xmedia_vb_release_block(vb_handle);
xmedia_vb_destroy_pool(pool_id);
xmedia_vb_exit();
return ret;
}
ret = xmedia_vgs_create_job(&handle);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d create vgs job failed\n", pipe, chn);
xmedia_vgs_exit();
xmedia_vb_release_block(vb_handle);
xmedia_vb_destroy_pool(pool_id);
xmedia_vb_exit();
return ret;
}
memcpy(&task_info.img_in, in_frame, sizeof(xmedia_video_frame_info));
memcpy(&task_info.img_out, &out_frame, sizeof(xmedia_video_frame_info));
ret = xmedia_vgs_add_task_rotation(handle, &task_info, rot);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d add vgs task failed\n", pipe, chn);
xmedia_vgs_cancel_job(handle);
xmedia_vgs_exit();
xmedia_vb_release_block(vb_handle);
xmedia_vb_destroy_pool(pool_id);
xmedia_vb_exit();
return ret;
}
ret = xmedia_vgs_submit_job(handle);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d submit vgs job failed\n", pipe, chn);
xmedia_vgs_cancel_job(handle);
xmedia_vgs_exit();
xmedia_vb_release_block(vb_handle);
xmedia_vb_destroy_pool(pool_id);
xmedia_vb_exit();
return ret;
}
ret = xmedia_vgs_wait_job(handle, 2000);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d wait vgs job failed\n", pipe, chn);
xmedia_vgs_exit();
xmedia_vb_release_block(vb_handle);
xmedia_vb_destroy_pool(pool_id);
xmedia_vb_exit();
return ret;
}
save_yuv_8bit_to_file(&task_info.img_out.frame, fd);
xmedia_vgs_exit();
xmedia_vb_release_block(vb_handle);
xmedia_vb_destroy_pool(pool_id);
xmedia_vb_exit();
return XMEDIA_SUCCESS;
}
xmedia_void dump_yuv(xmedia_s32 pipe, xmedia_s32 chn, xmedia_u32 cnt)
{
xmedia_s32 ret;
FILE *fd = XMEDIA_NULL;
xmedia_char file_name[FILE_NAME_LEN];
xmedia_video_frame_info frame_info;
ret = make_yuv_file_name(pipe, chn, cnt, file_name);
if (ret != XMEDIA_SUCCESS) {
return;
}
fd = fopen(file_name, "wb");
if (fd == XMEDIA_NULL) {
r_printf("opne file failed\n");
return;
}
while (cnt--) {
ret = xmedia_vi_acquire_chn_frame(pipe, chn, &frame_info, MAX_WAIT_TIME);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d get chn frame %u failed with 0x%x\n", pipe, chn, cnt, ret);
continue;
}
if (frame_info.frame.compress_mode != XMEDIA_VIDEO_COMPRESS_MODE_NONE ||
frame_info.frame.video_fmt != XMEDIA_VIDEO_FMT_LINEAR) {
submit_vgs_to_transform(pipe, chn, &frame_info, fd);
} else {
save_yuv_8bit_to_file(&frame_info.frame, fd);
}
ret = xmedia_vi_release_chn_frame(pipe, chn, &frame_info);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d release chn frame %u failed with 0x%x\n", pipe, chn, cnt, ret);
}
}
fclose(fd);
}
xmedia_s32 main(xmedia_s32 argc, xmedia_char *argv[])
{
xmedia_s32 ret;
xmedia_s32 pipe;
xmedia_s32 chn;
xmedia_u32 frame_cnt = 0;
xmedia_u32 origin_depth;
xmedia_u32 depth;
printf("\nNOTIC: this tool only can be used for TESTING !!!\n");
printf("\n To see more usage, please enter: ./vi_chn_dump -h\n\n");
if (argc > 1) {
if (strncmp(argv[1], "-h", 2) == 0) {
vi_chn_dump_usage();
exit(XMEDIA_SUCCESS);
}
}
if (argc < 4) {
vi_chn_dump_usage();
exit(XMEDIA_SUCCESS);
}
pipe = atoi(argv[1]);
if (pipe < 0 || pipe >= VI_MAX_PIPE_NUM) {
r_printf("pipe %d is illegal!\n", pipe);
return XMEDIA_FAILURE;
}
chn = atoi(argv[2]);
if (chn < 0 || chn >= VI_MAX_CHN_NUM) {
r_printf("chn %d is illegal!\n", chn);
return XMEDIA_FAILURE;
}
frame_cnt = atoi(argv[3]);
if (frame_cnt < 0 || frame_cnt > MAX_FRAME_CNT) {
r_printf("frame cnt %d is illegal!\n", frame_cnt);
return XMEDIA_FAILURE;
}
ret = xmedia_vi_init();
if (ret != XMEDIA_SUCCESS) {
r_printf("vi init failed\n");
return ret;
}
ret = xmedia_vi_get_chn_depth(pipe, chn, &origin_depth);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d get chn depth failed with 0x%x", pipe, chn, ret);
xmedia_vi_exit();
return ret;
}
depth = YUV_DUMP_DEPTH;
ret = xmedia_vi_set_chn_depth(pipe, chn, depth);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d set chn depth failed with 0x%x", pipe, chn, ret);
xmedia_vi_exit();
return ret;
}
dump_yuv(pipe, chn, frame_cnt);
depth = origin_depth;
ret = xmedia_vi_set_chn_depth(pipe, chn, depth);
if (ret != XMEDIA_SUCCESS) {
r_printf("pipe %d chn %d set chn depth failed with 0x%x", pipe, chn, ret);
xmedia_vi_exit();
return ret;
}
xmedia_vi_exit();
return XMEDIA_SUCCESS;
}