| 
 | 
 
平台:TQ2440,内核2.4.30,摄像头中星微uvc无驱的 
 
终端提示信息如下:::: 
USB Camera Test 
dth = 160   Height = 120 
frame buffer: 480x272,  16bpp, 0x3fc00byte= 261120 
 
 
部分代码如下: 
int main(int argc, char** argv) 
{ 
    int numBufs; 
    printf("USB Camera Test\n"); 
 
    int fd = open("/dev/video0", O_RDWR, 0);            //打开摄像头设备,使用阻塞方式打开 
    if (fd<0) 
    { 
        printf("open error\n"); 
        return  -1; 
    } 
 
    struct v4l2_format fmt;                        //设置获取视频的格式 
    memset( &fmt, 0, sizeof(fmt)); 
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;                //视频数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE 
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;            //视频源的格式为JPEG或YUN4:2:2或RGB 
    fmt.fmt.pix.width = 640;                    //设置视频宽度 
    fmt.fmt.pix.height = 480;                    //设置视频高度 
    if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)                //使配置生效 
    { 
        printf("set format failed\n"); 
        return -1; 
    } 
 
    struct v4l2_requestbuffers req;                    //申请帧缓冲 
    memset(&req, 0, sizeof (req)); 
    req.count = 1;                            //缓存数量,即可保存的图片数量 
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;                //数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE 
    req.memory = V4L2_MEMORY_MMAP;                    //存储类型:V4L2_MEMORY_MMAP或V4L2_MEMORY_USERPTR 
    if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1)            //使配置生效 
    { 
        perror("request buffer error \n"); 
        return -1; 
    } 
 
    VideoBuffer *buffers = calloc(req.count, sizeof(VideoBuffer));    //将VIDIOC_REQBUFS获取内存转为物理空间 
//    printf("sizeof(VideoBuffer) is %d\n", sizeof(VideoBuffer)); 
    struct v4l2_buffer buf; 
    for (numBufs = 0; numBufs < req.count; numBufs++) 
    { 
        memset( &buf, 0, sizeof(buf)); 
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;            //数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE 
        buf.memory = V4L2_MEMORY_MMAP;                //存储类型:V4L2_MEMORY_MMAP(内存映射)或V4L2_MEMORY_USERPTR(用户指针) 
        buf.index = numBufs; 
        if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0)        //使配置生效 
        { 
            printf("VIDIOC_QUERYBUF error\n"); 
            return -1; 
        } 
//        printf("buf len is %d\n", sizeof(buf)); 
        buffers[numBufs].length = buf.length; 
        buffers[numBufs].offset = (size_t) buf.m.offset; 
        buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, 
            MAP_SHARED, fd, buf.m.offset);            //使用mmap函数将申请的缓存地址转换应用程序的绝对地址 
#if 0 
        printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d\n", 
                buffers[numBufs].length, buffers[numBufs].offset, 
                buffers[numBufs].start[0]); 
 
        printf("buf2 len is %d\n", sizeof(buffers[numBufs].start)); 
#endif 
        if (buffers[numBufs].start == MAP_FAILED) 
        { 
            perror("buffers error\n"); 
            return -1; 
        } 
        if (ioctl(fd, VIDIOC_QBUF, &buf) < 0)            //放入缓存队列 
        { 
            printf("VIDIOC_QBUF error\n"); 
            return -1; 
        } 
 
    } 
 
    enum v4l2_buf_type type;                    //开始视频显示 
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;                //数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE 
    if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) 
    { 
        printf("VIDIOC_STREAMON error\n"); 
        return -1; 
    } 
 
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;                //数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE 
    if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)                //读取视频源格式 
    { 
        printf("get format failed\n"); 
        return -1; 
    } 
    else 
    { 
        printf("Picture:Width = %d   Height = %d\n", fmt.fmt.pix.width, fmt.fmt.pix.height); 
//        printf("Image size = %d\n", fmt.fmt.pix.sizeimage); 
//        printf("pixelformat = %d\n", fmt.fmt.pix.pixelformat); 
    } 
 
    FILE * fd_y_file = 0; 
    int a=0; 
    int k = 0; 
 
    //设置显卡设备framebuffer 
    struct jpeg_decompress_struct cinfo; 
    struct jpeg_error_mgr jerr; 
    FILE *infile;                            //Jpeg文件的句柄 
    unsigned char *buffer; 
 
    int fb; 
    char *fb_device; 
    unsigned int x; 
    unsigned int y; 
 
    if ((fb = open("/dev/fb0", O_RDWR)) < 0)            //打开显卡设备 
    { 
        perror(__func__); 
        return (-1); 
    } 
 
    //获取framebuffer的状态 
    fb_stat(fb);                            //获取显卡驱动中的长、宽和显示位宽 
    printf("frame buffer: %dx%d,  %dbpp, 0x%xbyte= %d\n",  
        fbdev.fb_width, fbdev.fb_height, fbdev.fb_bpp, fbdev.fb_size, fbdev.fb_size); 
 
    //映射framebuffer的地址 
    fbdev.fb_mem = mmap (NULL, fbdev.fb_size, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0); 
                                    //映射显存地址 
    fbdev.fb = fb; 
    //预览采集到的图像 
    while (1) 
    { 
 
        //如果把处理JPEG格式的数据和显示程序分离,把处理JPEG部分的数据作成一个新的线程,预览时会更加流畅。 
        for (numBufs = 0; numBufs < req.count; numBufs++) 
        { 
            char s[15]; 
            sprintf(s, "%d.jpg", a); 
            if ((fd_y_file = fopen(s, "wb")) < 0) 
            { 
                printf("Unable to create y frame recording file\n"); 
                return -1; 
            } 
 
            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        //取得原始采集数据 
            buf.memory = V4L2_MEMORY_MMAP;            //存储类型:V4L2_MEMORY_MMAP(内存映射)或V4L2_MEMORY_USERPTR(用户指针) 
            if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0)//程序运行到这里就不动了,不知道什么原因? 
            { 
                perror("VIDIOC_DQBUF failed.\n"); 
                return -1; 
            } 
 
 
 
 
 |   
 
 
 
 |