Cessi 2016-12-13 08:32 采纳率: 0%
浏览 2958

如何有效的从内核拷贝数据到用户空间

```struct v4l2_mxc_offset {
unsigned int u_offset;
unsigned int v_offset;
};

struct testbuffer
{
unsigned char *start;
size_t offset;
unsigned int length;
};

struct v4l2_buffer buf;
struct v4l2_capability cap;
struct v4l2_dbg_chip_ident chip;
struct v4l2_frmsizeenum fsize;
struct v4l2_streamparm parm;
struct v4l2_crop crop;
struct v4l2_format fmt;
struct v4l2_mxc_offset off;
int g_camera_framerate = 160;
int g_capture_mode = 0;
int g_input = 0;
int g_in_width = SEND_X;
int g_in_height = SEND_Y;
int g_out_width = SEND_X;
int g_out_height = SEND_Y;
int g_top = 0;
int g_left = 0;
int g_cap_fmt = V4L2_PIX_FMT_RGB24;
int g_extra_pixel = 0;
//extern
struct testbuffer buffers[TEST_BUFFER_NUM];

static int start_capturing(int fd_v4l)
{
unsigned int i;
struct v4l2_buffer buf;
enum v4l2_buf_type type;
printCSILog(" ---- start_capturing ----\n");
for (i = 0; i < TEST_BUFFER_NUM; i++)
{
printCSILog(" ---- start_capturing ----\n");
memset(&buf, 0, sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (ioctl(fd_v4l, VIDIOC_QUERYBUF, &buf) < 0)
{
printCSILog("VIDIOC_QUERYBUF error\n");
return -1;
}
printCSILog("User space Every Buffer Length = %d \n", buf.length);
buffers[i].length = buf.length;
buffers[i].offset = (size_t) buf.m.offset;
buffers[i].start = (unsigned char *)mmap(NULL, buffers[i].length,
PROT_READ | PROT_WRITE, MAP_SHARED,
fd_v4l, buffers[i].offset);
memset(buffers[i].start, 0xFF, buffers[i].length);
}

    for (i = 0; i < TEST_BUFFER_NUM; i++)
    {
            memset(&buf, 0, sizeof (buf));
            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.memory = V4L2_MEMORY_MMAP;
            buf.index = i;
            buf.m.offset = buffers[i].offset;
            if (g_extra_pixel){
                buf.m.offset += g_extra_pixel *
                    (g_out_width + 2 * g_extra_pixel) + g_extra_pixel;
            }

            if (ioctl (fd_v4l, VIDIOC_QBUF, &buf) < 0) {
                    if(PRINTFLAG==1) printf("VIDIOC_QBUF error\n");
                    return -1;
            }
    }

    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl (fd_v4l, VIDIOC_STREAMON, &type) < 0) {
            if(PRINTFLAG==1) printf("VIDIOC_STREAMON error\n");
            return -1;
    }
    return 0;

}

int init_csi()
{
int ret;
csi_fd = open(CAMERA_DEVICE, O_RDWR);
if(csi_fd < 0){
printf("open %s failed.\n", CAMERA_DEVICE);
return -1;
}
ioctl(csi_fd, VIDIOC_QUERYCAP, &cap);
if(ret < 0){
printf("VIDIOC_QUERYCAP failed(%d)\n", ret);
return ret;
}else{
printf("Capability Informations:\ndriver: %s\ncard: %d\nbus_info: %d\nversion: %08X\ncapabilities: %08X\n", cap.driver, cap.card, cap.bus_info, cap.version, cap.capabilities);
}

if (ioctl(csi_fd, VIDIOC_DBG_G_CHIP_IDENT, &chip))
{
    printf("VIDIOC_DBG_G_CHIP_IDENT failed.\n");
    return -1;
}else{
    printf("sensor chip is %s\n", chip.match.name);
}
printf("sensor supported frame size:\n");
fsize.index = 0;
while (ioctl(csi_fd, VIDIOC_ENUM_FRAMESIZES, &fsize) >= 0) {
    printCSILog(" %dx%d\n", fsize.discrete.width, fsize.discrete.height);
    fsize.index++;
}

parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm.parm.capture.timeperframe.numerator = 1;
parm.parm.capture.timeperframe.denominator = g_camera_framerate;
parm.parm.capture.capturemode = g_capture_mode;

if (ioctl(csi_fd, VIDIOC_S_PARM, &parm) < 0)
{
    printCSILog("VIDIOC_S_PARM failed\n");
    return -1;
}

if (ioctl(csi_fd, VIDIOC_S_INPUT, &g_input) < 0)
{
    printCSILog("VIDIOC_S_INPUT failed\n");
    return -1;
}

crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(csi_fd, VIDIOC_G_CROP, &crop) < 0)
{
    printCSILog("VIDIOC_G_CROP failed\n");
    return -1;
}

crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c.width = g_in_width;
crop.c.height = g_in_height;
crop.c.top = g_top;
crop.c.left = g_left;
if (ioctl(csi_fd, VIDIOC_S_CROP, &crop) < 0)
{
    printCSILog("VIDIOC_S_CROP failed\n");
    return -1;
}


fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.pixelformat = g_cap_fmt;
fmt.fmt.pix.width = g_out_width;
fmt.fmt.pix.height = g_out_height;
if (g_extra_pixel){
    off.u_offset = (2 * g_extra_pixel + g_out_width) * (g_out_height + g_extra_pixel)
         - g_extra_pixel + (g_extra_pixel / 2) * ((g_out_width / 2)
         + g_extra_pixel) + g_extra_pixel / 2;
    off.v_offset = off.u_offset + (g_extra_pixel + g_out_width / 2) *
        ((g_out_height / 2) + g_extra_pixel);
    fmt.fmt.pix.bytesperline = g_out_width + g_extra_pixel * 2;
    fmt.fmt.pix.priv = (unsigned int) &off;
    fmt.fmt.pix.sizeimage = (g_out_width + g_extra_pixel * 2 )
        * (g_out_height + g_extra_pixel * 2) * 3 / 2;
} else {
    fmt.fmt.pix.bytesperline = g_out_width;
    fmt.fmt.pix.priv = 0;
    fmt.fmt.pix.sizeimage = 0;
}
   printf("set format as: with=%d\t height=%d\t bytesperline=%d\t sizeimage=%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height,fmt.fmt.pix.bytesperline,fmt.fmt.pix.sizeimage);
if (ioctl(csi_fd, VIDIOC_S_FMT, &fmt) < 0)
{
    printCSILog("set format failed\n");
    return -1;
}


struct v4l2_requestbuffers req;
memset(&req, 0, sizeof (req));
req.count = TEST_BUFFER_NUM;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;

if (ioctl(csi_fd, VIDIOC_REQBUFS, &req) < 0)
{
    printCSILog("v4l_capture_setup: VIDIOC_REQBUFS failed\n");
    return -1;
}


fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(csi_fd, VIDIOC_G_FMT, &fmt) < 0)
{
    printCSILog("get format failed\n");
    return -1;
}
else
{
    printCSILog("\t Width = %d", fmt.fmt.pix.width);
    printCSILog("\t Height = %d", fmt.fmt.pix.height);
    printCSILog("\t Image size = %d\n", fmt.fmt.pix.sizeimage);
    printCSILog("\t pixelformat = %d\n", fmt.fmt.pix.pixelformat);
}


if (start_capturing(csi_fd) < 0)
{
    printCSILog("start_capturing failed\n");
    return -1;
}
return csi_fd;

}

int get_one_picture(struct video_frame_header *p_video_frame_header)
{
int i_cs=0;
int ret;

// memset(&buf, 0, sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;

// printCSILog("Begin get one picture...\r\n");

// printf("FILE :%s ,func : %s ,LINE :%d\n",__FILE__,__func__,__LINE__);

if (ioctl (csi_fd, VIDIOC_DQBUF, &buf) < 0) {
    printf("LINE : %d VIDIOC_DQBUF failed.\n",__LINE__);
}else{

// printf("FILE :%s ,func : %s ,LINE :%d\n",__FILE__,__func__,__LINE__);
// printf("******************************length=%d\n", buffers[buf.index].length);

p_video_frame_header->camera_num  = real_CAMERA_NUM;
p_video_frame_header->csi_frame_count = *(unsigned int *)((char *)buffers[buf.index].start+4);
p_video_frame_header->frame_rates = *(unsigned int *)((char *)buffers[buf.index].start+8);
p_video_frame_header->xSize = real_X_SIZE_OF_FRAME;
p_video_frame_header->ySize =real_Y_SIZE_OF_FRAME;
p_video_frame_header->bpp = real_FRAME_BPP=8;
p_video_frame_header->max= *(unsigned int *)((char *)buffers[buf.index].start+24);
p_video_frame_header->min= *(unsigned int *)((char *)buffers[buf.index].start+28);
p_video_frame_header->position = *(unsigned int *)((char *)buffers[buf.index].start+32);

char *p_temp=(char *)buffers[buf.index].start+SIZE_OF_FRAME_HEAD;

// printf("__________________________LINE :%d ,csi_frame_count_temp =%d \n",__LINE__,p_video_frame_header->csi_frame_count);
write(led_fd,&led_num[1], 1);
// memcpy((void *)(((char *)p_video_frame_header)+sizeof(struct video_frame_header)),(char *)buffers[buf.index].start+SIZE_OF_FRAME_HEAD,DATA_SIZE/2);
memcpy(globalImageCache[4],p_temp,DATA_SIZE);
// memcpy(globalImageCache[4],globalImageCache[3],DATA_SIZE);
write(led_fd, &led_num[0], 1);
// printf("FILE :%s ,func : %s ,LINE :%d\n",__FILE__,__func__,__LINE__);
if (ioctl (csi_fd, VIDIOC_QBUF, &buf) < 0) {
printf("VIDIOC_QBUF failed\n");
}
// printf("FILE :%s ,func : %s ,LINE :%d\n",__FILE__,__func__,__LINE__);
// printCSILog("buf.index %d\n", buf.index);
// printf("%s : frame _____%d \n",__func__,p_video_frame_header->csi_frame_count);

csi_get_num++;
last_frame=p_video_frame_header->csi_frame_count;
if(last_csi_count!=0){                                  //判断是否丢帧,last_csi_count初始化为0的,因此第一次不会误进入此处
    if((p_video_frame_header->csi_frame_count)>(last_csi_count+1)){                                             //丢帧

// printf("%s : Loss frame _____%d \n",__func__,p_video_frame_header->csi_frame_count);
if(csi_loss_frame_count csi_loss[csi_loss_frame_count]=p_video_frame_header->csi_frame_count;
}

        csi_loss_frame_count=csi_loss_frame_count+p_video_frame_header->csi_frame_count-last_csi_count;
    }

}else{
    first_frame=p_video_frame_header->csi_frame_count;
}

last_csi_count=p_video_frame_header->csi_frame_count;                   //记录信息
}
return 0;

}


如题,在get_one_picture()中,memcpy内核的指针和用户及空间的指针差别非常大,时间相差近十倍

  • 写回答

1条回答 默认 最新

  • dabocaiqq 2016-12-17 04:35
    关注
    评论

报告相同问题?

悬赏问题

  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器