天嵌 ARM开发社区

 找回密码
 注册
查看: 1464|回复: 3

求针对YUYV格式摄像头的程序或相应链接?

[复制链接]
回帖奖励 40 回复本帖可获得 8 奖励! 每人限 1 次
wuqijun09 发表于 2014-4-4 22:49:09 | 显示全部楼层 |阅读模式
本帖最后由 wuqijun09 于 2014-4-5 16:23 编辑

请问天嵌有没有针对YUYV格式摄像头的程序,我看板子自带的程序都是对MJPEG格式的,我的摄像头只能是YUYV格式的,调试了好久就是不能显示图像,求大神教教我 !
 楼主| wuqijun09 发表于 2014-4-7 16:56:29 | 显示全部楼层
http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html
 楼主| wuqijun09 发表于 2014-4-8 09:48:42 | 显示全部楼层
/*************************************

NAME:usb_camera.c
COPYRIGHT:www.embedsky.net

*************************************/

#include <errno.h>
#include <sys/types.h>       
#include <sys/stat.h>       
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>   
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <asm/types.h>
#include <linux/videodev2.h>
#include <sys/mman.h>
#include <string.h>
#include <malloc.h>
#include <linux/fb.h>
#include <jpeglib.h>
#include <jerror.h>

typedef struct VideoBuffer
{
        unsigned char *start;
        size_t offset;
        size_t length;
} VideoBuffer;

struct fb_dev
{
        //for frame buffer
        int fb;
        void *fb_mem;        //frame buffer mmap
        int fb_width, fb_height, fb_line_len, fb_size;
        int fb_bpp;
} fbdev;

//得到framebuffer的长、宽和位宽,成功则返回0,失败返回-1
int fb_stat(int fd)
{
        struct fb_fix_screeninfo fb_finfo;
        struct fb_var_screeninfo fb_vinfo;

        if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo))
        {
                perror(__func__);
                return (-1);
        }

        if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo))
        {
                perror(__func__);
                return (-1);
        }

        fbdev.fb_width = fb_vinfo.xres;
        fbdev.fb_height = fb_vinfo.yres;
        fbdev.fb_bpp = fb_vinfo.bits_per_pixel;
        fbdev.fb_line_len = fb_finfo.line_length;
        fbdev.fb_size = fb_finfo.smem_len;

        return (0);
}

int convert_yuv_to_rgb_pixel(int y, int u, int v)
{
        unsigned int pixel32 = 0;
        unsigned char *pixel = (unsigned char *) &pixel32;
        int r, g, b;
        r = y + (1.370705 * (v - 128));
        g = y - (0.698001 * (v - 128)) - (0.337633 * (u - 128));
        b = y + (1.732446 * (u - 128));
        if (r > 255)
                r = 255;
        if (g > 255)
                g = 255;
        if (b > 255)
                b = 255;
        if (r < 0)
                r = 0;
        if (g < 0)
                g = 0;
        if (b < 0)
                b = 0;
        pixel[0] = r * 220 / 256;
        pixel[1] = g * 220 / 256;
        pixel[2] = b * 220 / 256;
        return pixel32;
}
int YUYVToRGB(unsigned char *yuv, unsigned char *rgb, unsigned int width,
                unsigned int height)
{
        unsigned int in, out = 0;
        unsigned int pixel_16;
        unsigned char pixel_24[3];
        unsigned int pixel32;
        int y0, u, y1, v;
        for (in = 0; in < width * height * 2; in += 4)
        {
                pixel_16 = yuv[in + 3] << 24 | yuv[in + 2] << 16 | yuv[in + 1] << 8
                                | yuv[in + 0];
                y0 = (pixel_16 & 0x000000ff);
                u = (pixel_16 & 0x0000ff00) >> 8;
                y1 = (pixel_16 & 0x00ff0000) >> 16;
                v = (pixel_16 & 0xff000000) >> 24;
                pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
                pixel_24[0] = ((pixel32 & 0x000000ff)>>3)&0x1f;      //r
                pixel_24[1] = (((pixel32 & 0x0000ff00) >> 8)>>2)&0x1f;  //g
                pixel_24[2] = (((pixel32 & 0x00ff0000) >> 16)>>3)&0x1f;  //b
                rgb[out++] = pixel_24[0];
                rgb[out++] = pixel_24[1];
                rgb[out++] = pixel_24[2];
                pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
                pixel_24[0] = ((pixel32 & 0x000000ff)>>3)&0xif;      //r
                pixel_24[1] = (((pixel32 & 0x0000ff00) >> 8)>>2)&0x1f;  //g
                pixel_24[2] = (((pixel32 & 0x00ff0000) >> 16)>>3)&0x1f;  //b
                rgb[out++] = pixel_24[0];
                rgb[out++] = pixel_24[1];
                rgb[out++] = pixel_24[2];
        }
        return 0;
}



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 = 320;                                        //设置视频宽度
        fmt.fmt.pix.height = 240;                                        //设置视频高度
        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 (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
        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)
        {
                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;
                        }
                        //buffer = (unsigned char *) malloc(320*240*3);
                        unsigned char *ptcur = buffers[numBufs].start;                //开始霍夫曼解码
                        YUYVToRGB(ptcur, fbdev.fb_mem, 320, 240);

                        //获取下一帧视频数据
                        if (ioctl(fd, VIDIOC_QBUF, &buf) < 0)
                        {
                                printf("VIDIOC_QBUF error\n");
                                return -1;
                        }
                }
        }
        fb_munmap(fbdev.fb_mem, fbdev.fb_size);                                        //释放framebuffer映射
        close(fb);                                                                //关闭Framebuffer设备

        close(fd);
}
这是我修改的天嵌的代码,但触摸屏却显示花屏不能显示图像,求高手指点啊!
 楼主| wuqijun09 发表于 2014-4-8 10:41:24 | 显示全部楼层
而且我设置的视频是320*240但返回的却是176*144,设置没有生效么?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-6-2 12:42 , Processed in 1.031250 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表