木子临枫 2023-04-24 11:19 采纳率: 28.6%
浏览 33
已结题

zynqMP使用linux显示tpg图片数据有撕裂

VDMA读取图片数据有撕裂
故障现象如图:

img

使用硬件平台zynqMP
工具pelalinux 生成的linux工程
硬件框图:

img

linux应用操作:
配置设备树

&v_tpg_0{
        compatible = "xlnx,v-tpg-8.0";
        xlnx,ppc = <1>;
        reset-gpios = <&gpio 81 1>;
        xlnx,max-width = <1280>;
        xlnx,max-height = <720>;
        ports {
            #address-cells = <1>;
            #size-cells = <0>;

            port@0 {
                reg = <0>;

                xlnx,video-format = <XVIP_VF_YUV_422>;
                xlnx,video-width = <8>;

                tpg_out: endpoint {
                    remote-endpoint = <&csc_in>;
                };
            };
        };
};


&v_proc_ss_0{
    compatible = "xlnx,v-vpss-csc";
    reset-gpios = <&gpio 80 1>;
    csc_ports: ports {
        #address-cells = <1>;
        #size-cells = <0>;
        xlnx,max-width = <1280>;
        xlnx,max-height = <720>;

        csc_port0: port@0 {
            reg = <0>;
            xlnx,video-format = <XVIP_VF_YUV_422>;
            xlnx,video-width = <8>;
            csc_in: endpoint {
                remote-endpoint = <&tpg_out>;
            };
        };
        csc_port1: port@1 {
            reg = <1>;
            xlnx,video-format = <XVIP_VF_RBG>;
            xlnx,video-width = <8>;
            csc_out: endpoint {
                remote-endpoint = <&vcap_tpg_in>;
            };
        };
    };
};

&amba_pl {
    vcap_tpg{
        compatible = "xlnx,video";
        dma-names = "port0";
        dmas = <&axi_vdma_0 1>;        

        ports{
            #address-cells = <1>;
            #size-cells = <0>;

            port@0{
                reg = <0>;
                direction = "input";
                vcap_tpg_in: endpoint{
                    remote-endpoint = <&csc_out>;
                };
            };            
        };
    };
};
root@xilinx-3eg:/mnt/dervice_ov5640/char_appcam# media-ctl -p -d /dev/media0
Media controller API version 5.4.0

Media device information
------------------------
driver          xilinx-video
model           Xilinx Video Composite Device
serial
bus info
hw revision     0x0
driver version  5.4.0

Device topology
- entity 1: vcap_tpg output 0 (1 pad, 1 link)
            type Node subtype V4L flags 0
            device node name /dev/video0
        pad0: Sink
                <- "80050000.v_proc_ss":1 [ENABLED]

- entity 5: 80000000.v_tpg (1 pad, 1 link)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev0
        pad0: Source
                [fmt:UYVY8_1X16/1280x720@1/30 field:none colorspace:srgb]
                -> "80050000.v_proc_ss":0 [ENABLED]

- entity 7: 80050000.v_proc_ss (2 pads, 2 links)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev1
        pad0: Sink
                [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb]
                <- "80000000.v_tpg":0 [ENABLED]
        pad1: Source
                [fmt:RBG888_1X24/1280x720 field:none colorspace:rec709]
                -> "vcap_tpg output 0":0 [ENABLED]

使用V4L2 获取图像数据

#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 <linux/videodev2.h>
#include <linux/v4l2-subdev.h>
#include <linux/fb.h>
#include <poll.h>
#include <time.h>
#include <linux/xilinx-v4l2-controls.h>
#include <linux/sched.h>
#include <sched.h>

#define VIDEO_DEVICE_NAME "/dev/video0"
#define V4LSUB_DEVICE_NAME "/dev/v4l-subdev0" 
#define FRAMEBUFFER_NAME "/dev/fb0" 
#define IMAGE_FILE "f1.rgb"
#define BUFFER_COUNT 10

struct buffer {
    void *start;
    size_t length;
};

struct buffer* buffer_mmap;

char *fbp;
int fbfd;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;




void Mem_Cpy(void *pTag,const void *pSrc,int nLen)
{
       unsigned int *pTagBuf = (unsigned int *)pTag;
    unsigned int *pSrcBuf = (unsigned int *)pSrc;
 
        int i = 0;
    for(i = 0;i < nLen / 4;i++)
    {
                pTagBuf[i] = pSrcBuf[i];
    }
 
}







int GetSensorFormat(int fd)
{
    struct v4l2_subdev_format fmt;
    memset(&fmt, 0, sizeof(fmt));
    fmt.which = 1;
    if (-1 == ioctl(fd, VIDIOC_SUBDEV_G_FMT, &fmt)){
        printf("VIDIOC_SUBDEV_G_FMT fail\n");
                return -1;    
    }
    printf("fmt.which=%d\n",(int)fmt.which);
    printf("fmt.format.width=%d\n",(int)fmt.format.width);
    printf("fmt.format.height=%d\n",(int)fmt.format.height);
    printf("fmt.format.code=%d\n",(int)fmt.format.code);
    printf("fmt.format.field=%d\n",(int)fmt.format.field);
    printf("fmt.format.colorspace=%d\n",(int)fmt.format.colorspace);

    return 0;
}

int SetSensorFormat(int fd)
{
    struct v4l2_subdev_format fmt;
    struct v4l2_control ctrl;

    ctrl.id = V4L2_CID_TEST_PATTERN;
    ctrl.value = 10;
    ioctl(fd,VIDIOC_S_CTRL,&ctrl);
    ctrl.id =  V4L2_CID_XILINX_TPG_MOTION_SPEED;
    ctrl.value = 10;
    ioctl(fd,VIDIOC_S_CTRL,&ctrl);
        ctrl.id =  V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED;
    ctrl.value = 10;
    ioctl(fd,VIDIOC_S_CTRL,&ctrl);


    



    return 0;
}

int QueryVideoCap(int fd)
{
    struct v4l2_capability cap;
        if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap)) {
                printf("VIDIOC_QUERYCAP fail\n");
                return -1;
        }
    printf("cap.driver: %s\n", cap.driver);
    printf("cap.card: %s\n", cap.card);
    printf("cap.bus_info: %s\n", cap.bus_info);
    printf("cap.capabilities= 0x%x\n", cap.capabilities);
    printf("cap.device_caps= 0x%x\n", cap.device_caps);
    
    return 0;
}

int GetVideoFormat(int fd)
{
    struct v4l2_format fmt;
    memset(&fmt, 0, sizeof(fmt));
    fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if(ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
    {
        printf("VIDIOC_G_FMT failed\n");
        return -1;                
    }
    //printf stream format
    printf("Stream format informations:\n");
    printf(" type: %d\n", fmt.type);            
    printf(" width: %d\n", fmt.fmt.pix.width);
    printf(" height: %d\n", fmt.fmt.pix.height);
    char fmtstr[8];        
    memset(fmtstr, 0, 8);
    memcpy(fmtstr, &fmt.fmt.pix.pixelformat, 8);    
    printf(" pixelformat: %s\n", fmtstr);
    printf(" field: %d\n", fmt.fmt.pix.field);
    printf(" bytesperline: %d\n", fmt.fmt.pix.bytesperline);
    printf(" sizeimage: %d\n", fmt.fmt.pix.sizeimage);
    printf(" colorspace: %d\n", fmt.fmt.pix.colorspace);

    return 0;
}

int SetVideoFormat(int fd)
{
    struct v4l2_format fmt;
    memset(&fmt, 0, sizeof(struct v4l2_format));
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width =1280;
    fmt.fmt.pix.height =720;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
    fmt.fmt.pix.field = V4L2_FIELD_NONE;

    if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
        printf("Set format fail\n");
        return -1;
    }   

    printf("width = %d\n", fmt.fmt.pix.width);
    printf("height = %d\n", fmt.fmt.pix.height);
    printf("pixelformat = %d\n", fmt.fmt.pix.pixelformat);
    return 0;
}

static void errno_exit(const char *s)
{
    printf("ERR(%s):%s failed\r\n", __func__, s);  //显示错误函数
    fprintf(stderr,"%s error %d, %s\r\n",s ,errno, strerror(errno));
    
    
    exit(EXIT_FAILURE);
}

int init_mmap(int fd)
{
        struct v4l2_requestbuffers req;

        req.count = BUFFER_COUNT;
        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        req.memory = V4L2_MEMORY_MMAP;

       printf("BUFFER_COUNT is %d\n", BUFFER_COUNT);

        if (ioctl(fd, VIDIOC_REQBUFS, &req)<0) {
                printf("VIDIOC_REQBUFS fail\n");
        return -1;
        }
    
        if (req.count < 2) {
                printf("req.count is too small, req.count= %d\n", req.count);
        return -1;
        }


    buffer_mmap = (struct buffer*)calloc(req.count, sizeof(struct buffer));
    printf("buffer_mmap\r\n");

    struct v4l2_buffer buf;
    int i;

        for (i = 0; i < req.count; ++i) {
                
            memset(&buf, 0, sizeof(buf));

            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.memory = V4L2_MEMORY_MMAP;
            buf.index = i;

            if (ioctl(fd, VIDIOC_QUERYBUF, &buf)<0) {
                printf("VIDIOC_QUERYBUF fail\n");
                return -1;
            }

            buffer_mmap[i].length = buf.length;
            buffer_mmap[i].start =
                        mmap(NULL /* start anywhere */,
                              buf.length,
                              PROT_READ | PROT_WRITE /* required */,
                              MAP_SHARED /* recommended */,
                              fd, buf.m.offset);

            if (MAP_FAILED == buffer_mmap[i].start) {
                printf("mmap fail\n");
                return -1;
            }
            printf("buffer_mmap[%d].length= %d\n",i,(int)buffer_mmap[i].length);
        }
    
        for (i = 0; i < req.count; ++i) {
            memset(&buf, 0, sizeof(buf));
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory = V4L2_MEMORY_MMAP;
                buf.index = i;

            if (ioctl(fd, VIDIOC_QBUF, &buf)<0) {
                printf("VIDIOC_QBUF fail\n");
                return -1;
            }
        }


    enum v4l2_buf_type type;
    type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (ioctl(fd, VIDIOC_STREAMON, &type)<0) {

        printf("VIDIOC_STREAMON fail\n");
        errno_exit("STREAMON");

        return -1;
    }

    return 0;
}

int read_frame(int VideoFd, FILE *ImageFileFd)
{
        struct v4l2_buffer buf;
        int i, bytesused;

        memset(&buf, 0, sizeof(buf));

        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;

        if (0>ioctl(VideoFd, VIDIOC_DQBUF, &buf)) {
            printf("VIDIOC_DQBUF fail\n");
            return -1;
        }

        i = buf.index;
        bytesused = buf.bytesused;

        fwrite(buffer_mmap[i].start, bytesused, 1, ImageFileFd);
        fflush(ImageFileFd);

        if (0>ioctl(VideoFd, VIDIOC_QBUF, &buf)) {
            printf("read_frame VIDIOC_QBUF fail\n");
            
            return -1;
        }

        return 0;
}

int display(int VideoFd)
{
    struct timespec time_start,time_end;
    long long diff;
    struct v4l2_buffer buf;
    int bytesused;
    struct pollfd tfds[1];
    unsigned char* addr;
    unsigned char* image_store;
    fd_set fds;
    struct timeval tv;
    int ret;
    image_store=malloc(1280*720*3);    
    /*
    tfds[0].fd=VideoFd;
    tfds[0].events=POLLIN;
            if(poll(tfds, 1, -1)<=0){
                printf("poll fail\n");
                return -1;
            }
    */
        while(1)
        {
            /*
            if(poll(tfds, 1, -1)<=0){
                printf("poll fail\n");
                return -1;
            }
            */
            buf.bytesused = 0;
            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.memory = V4L2_MEMORY_MMAP;
            buf.field = V4L2_BUF_FLAG_QUEUED;
            if (0>ioctl(VideoFd, VIDIOC_DQBUF, &buf)) {
                printf("VIDIOC_DQBUF fail\n");
                return -1;
            }

        //usleep(3300);

            addr=(unsigned char*)(buffer_mmap[buf.index ].start);
            printf("buffer_mmap[buf.index] %d\r\n",buf.index);
            memcpy(fbp,addr,1280*720*3);
            printf("timestamp %ld   %ld\r\n",buf.timestamp.tv_sec,buf.timestamp.tv_usec);
            
            if (0>ioctl(VideoFd, VIDIOC_QBUF, &buf)) {
                printf("read_frame VIDIOC_QBUF fail\n");
                return -1;
            }                   
        }
}

int display_initialize()
{
    long int screensize = 0;
    
    fbfd = open(FRAMEBUFFER_NAME, O_RDWR);
    if (fbfd==-1) {
        printf("Error: cannot open framebuffer device.\n");
        return -1;
    }
    printf("The framebuffer device was opened successfully.\n");
       
     /* Get fixed screen information */
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
        printf("Error reading fixed information.\n");
        return -1;
     }
    /* Get variable screen information */
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
        printf("Error reading variable information.\n");
        return -1;
    }
    /* show these information*/
    printf("vinfo.xres=%d\n",vinfo.xres);
    printf("vinfo.yres=%d\n",vinfo.yres);
    printf("vinfo.bits_per_bits=%d\n",vinfo.bits_per_pixel);
    printf("vinfo.xoffset=%d\n",vinfo.xoffset);
    printf("vinfo.yoffset=%d\n",vinfo.yoffset);
    printf("finfo.line_length=%d\n",finfo.line_length);
    /* Figure out the size of the screen in bytes */
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

    /* Map the device to memory */
    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,fbfd, 0);       
    if (fbp == MAP_FAILED) { 
        printf("Error: failed to map framebuffer device to memory.\n"); 
        close(fbfd);
        return -1;
    }
    printf("The framebuffer device was mapped to memory successfully.\n");
    memset(fbp,0,screensize);

    return 0;
}

int main(int argc, char **argv)
{
    struct sched_param schedParam;
    schedParam.sched_priority = 1; // 设置优先级为 99
    sched_setscheduler(0, SCHED_FIFO, &schedParam);
    int fd0,fd1;
    FILE* fd2;
        fd0 = open(VIDEO_DEVICE_NAME, O_RDWR);
    //    int flags = fcntl(fd0, F_GETFL, 0);
        //flags |= O_NONBLOCK;
      // fcntl(fd0, F_SETFL, flags);
        if (-1 == fd0) {
                printf("Cannot open %s\n", VIDEO_DEVICE_NAME);
                return -1;
        }
       fd1 = open(V4LSUB_DEVICE_NAME, O_RDWR);
        if (-1 == fd1) {
                printf("Cannot open %s\n", V4LSUB_DEVICE_NAME);
                return -1;
        }
        /*
        fd2 = fopen(IMAGE_FILE, "w+");
        if (fd2 == NULL) {
                printf("Cannot open %s\n", IMAGE_FILE);
                return -1;
        }
        */

    GetSensorFormat(fd1);
    SetSensorFormat(fd1);
    QueryVideoCap(fd0);
    GetVideoFormat(fd0);
    SetVideoFormat(fd0);
    GetVideoFormat(fd0);

    init_mmap(fd0);
       display_initialize();

      display(fd0);
      close(fd0);
      close(fd1);
      fclose(fd2);
      return 0;
}
  • 写回答

3条回答 默认 最新

  • Zyb0627 2023-04-24 11:46
    关注

    引用chatGPT作答,根据您提供的信息,可能是由于在缓冲区的转移期间,您的Linux应用程序的帧速率与ZynqMP硬件的帧速率不匹配,导致撕裂。这可能是因为您的Linux应用程序的帧速率低于硬件帧速率。

    您可以使用以下步骤来解决此问题:

    1.确保您的Linux应用程序的帧速率与硬件帧速率相同。

    2.尝试使用双缓冲技术,这可以帮助您减少撕裂。

    3.调整ZynqMP硬件的垂直同步信号,以与您的Linux应用程序匹配,以避免撕裂。

    4.如果您的硬件和Linux应用程序的帧速率不同,可以使用插值技术来使它们匹配。

    另外,您可以使用VSYNC同步来避免撕裂。您可以在设备树中启用VSYNC同步,如下所示:

    &axi_vdma_0 {
    status = "okay";
    clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
    clocks = <&clkc 31>, <&clkc 32>, <&clkc 33>;
    interrupt-parent = <&intc>;
    interrupts = <0 16 4>;
    xlnx,flush_on_fsync;
    xlnx,genlock_mode;
    xlnx,include_internal_genlock;
    xlnx,use_fsync;
    xlnx,vsync_genlock_master;
    xlnx,mm2s_dmacr_register_setting = <0x1004>;
    xlnx,s2mm_dmacr_register_setting = <0x1004>;
    xlnx,mm2s_genlock_src = <1>;
    xlnx,mm2s_sync_src = <1>;
    xlnx,s2mm_genlock_src = <1>;
    xlnx,s2mm_sync_src = <1>;
    xlnx,num_framebuffers = <3>;
    xlnx,video-format = "yuyv422";
    xlnx,width = <1280>;
    xlnx,height = <720>;
    xlnx,addr_width = <32>;
    xlnx,frame_counter_width = <16>;
    xlnx,sg_mmap;
    xlnx,use_axi_id;
    xlnx,use_mm2s;
    xlnx,use_s2mm;
    xlnx,s2mm_vdmacharaxi_register_setting = <0x1>;
    xlnx,mm2s_vdmacharaxi_register_setting = <0x1>;
    xlnx,mm2s_frame_buffer = <0x80000000>;
    xlnx,s2mm_frame_buffer = <0x800c0000>;
    };
    

    然后,在您的Linux应用程序中使用VSYNC同步:

    int vsync = 1;
    if (ioctl(fd, VIDIOC_S_CTRL, &vsync) < 0) {
    perror("Failed to set VSYNC");
    exit(1);
    }
    
    评论

报告相同问题?

问题事件

  • 系统已结题 5月2日
  • 创建了问题 4月24日

悬赏问题

  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥15 对于这个问题的算法代码
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题