首页 > 代码库 > 基于Tiny210开发板视频显示
基于Tiny210开发板视频显示
基于Tiny210开发板视频显示
1、写基于V4L2编程
========videodevice.h文件=========
#ifndef VIDEODEVICE_H #define VIDEODEVICE_H #include <string.h> #include <stdlib.h> #include <errno.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <asm/types.h> #include <linux/videodev2.h> #include <QString> #include <QObject> #define WIDTH 320 #define HEIGHT 240 #define CLEAR(x) memset(&(x), 0, sizeof(x)) class VideoDevice : public QObject { Q_OBJECT public: VideoDevice(QString dev_name); int open_device(); int close_device(); int init_device(); int start_capturing(); int stop_capturing(); int uninit_device(); int get_frame(void **, size_t*); int unget_frame(); private: int init_mmap(); struct buffer { void * start; size_t length; }; QString dev_name; int fd; buffer* buffers; unsigned int n_buffers; int index; signals: void display_error(QString); }; #endif // VIDEODEVICE_H
========videodevice.cpp文件=========
#include "videodevice.h" #include <stdio.h> VideoDevice::VideoDevice(QString dev_name) { this->dev_name = dev_name; this->fd = -1; this->buffers = NULL; this->n_buffers = 0; this->index = -1; } int VideoDevice::open_device() { fd = open(dev_name.toStdString().c_str(), O_RDWR/*|O_NONBLOCK*/, 0); // fd = open(dev_name.toStdString().c_str(), O_RDWR|O_NONBLOCK, 0); if(-1 == fd) { emit display_error(tr("open: %1").arg(QString(strerror(errno)))); return -1; } return 0; } int VideoDevice::close_device() { if(-1 == close(fd)) { emit display_error(tr("close: %1").arg(QString(strerror(errno)))); return -1; } return 0; } int VideoDevice::init_device() { v4l2_capability cap; v4l2_cropcap cropcap; v4l2_crop crop; v4l2_format fmt; if(-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap)) { if(EINVAL == errno) { emit display_error(tr("%1 is no V4l2 device").arg(dev_name)); } else { emit display_error(tr("VIDIOC_QUERYCAP: %1").arg(QString(strerror(errno)))); } return -1; } if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { emit display_error(tr("%1 is no video capture device").arg(dev_name)); return -1; } if(!(cap.capabilities & V4L2_CAP_STREAMING)) { emit display_error(tr("%1 does not support streaming i/o").arg(dev_name)); return -1; } CLEAR(cropcap); cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(0 == ioctl(fd, VIDIOC_CROPCAP, &cropcap)) { CLEAR(crop); crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; if(-1 == ioctl(fd, VIDIOC_S_CROP, &crop)) { if(EINVAL == errno) { // emit display_error(tr("VIDIOC_S_CROP not supported")); } else { emit display_error(tr("VIDIOC_S_CROP: %1").arg(QString(strerror(errno)))); return -1; } } } else { emit display_error(tr("VIDIOC_CROPCAP: %1").arg(QString(strerror(errno)))); return -1; } CLEAR(fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = WIDTH; fmt.fmt.pix.height = HEIGHT; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if(-1 == ioctl(fd, VIDIOC_S_FMT, &fmt)) { emit display_error(tr("VIDIOC_S_FMT").arg(QString(strerror(errno)))); return -1; } if(-1 == init_mmap()) { return -1; } fprintf(stderr,"========================\n"); return 0; } int VideoDevice::init_mmap() { v4l2_requestbuffers req; CLEAR(req); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if(-1 == ioctl(fd, VIDIOC_REQBUFS, &req)) { if(EINVAL == errno) { emit display_error(tr("%1 does not support memory mapping").arg(dev_name)); return -1; } else { emit display_error(tr("VIDIOC_REQBUFS %1").arg(QString(strerror(errno)))); return -1; } } if(req.count < 2) { emit display_error(tr("Insufficient buffer memory on %1").arg(dev_name)); return -1; } buffers = (buffer*)calloc(req.count, sizeof(*buffers)); if(!buffers) { emit display_error(tr("out of memory")); return -1; } for(n_buffers = 0; n_buffers < req.count; ++n_buffers) { v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = n_buffers; if(-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf)) { emit display_error(tr("VIDIOC_QUERYBUF: %1").arg(QString(strerror(errno)))); return -1; } buffers[n_buffers].length = buf.length; buffers[n_buffers].start = mmap(NULL, // start anywhere buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if(MAP_FAILED == buffers[n_buffers].start) { emit display_error(tr("mmap %1").arg(QString(strerror(errno)))); return -1; } } return 0; } int VideoDevice::start_capturing() { unsigned int i; for(i = 0; i < n_buffers; ++i) { v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory =V4L2_MEMORY_MMAP; buf.index = i; // fprintf(stderr, "n_buffers: %d\n", i); if(-1 == ioctl(fd, VIDIOC_QBUF, &buf)) { emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno)))); return -1; } } v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(-1 == ioctl(fd, VIDIOC_STREAMON, &type)) { emit display_error(tr("VIDIOC_STREAMON: %1").arg(QString(strerror(errno)))); return -1; } return 0; } int VideoDevice::stop_capturing() { v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) { emit display_error(tr("VIDIOC_STREAMOFF: %1").arg(QString(strerror(errno)))); return -1; } return 0; } int VideoDevice::uninit_device() { unsigned int i; for(i = 0; i < n_buffers; ++i) { if(-1 == munmap(buffers[i].start, buffers[i].length)) { emit display_error(tr("munmap: %1").arg(QString(strerror(errno)))); return -1; } } free(buffers); return 0; } int VideoDevice::get_frame(void **frame_buf, size_t* len) { v4l2_buffer queue_buf; CLEAR(queue_buf); queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; queue_buf.memory = V4L2_MEMORY_MMAP; if(-1 == ioctl(fd, VIDIOC_DQBUF, &queue_buf)) { switch(errno) { case EAGAIN: // perror("dqbuf"); return -1; case EIO: return -1 ; default: emit display_error(tr("VIDIOC_DQBUF: %1").arg(QString(strerror(errno)))); return -1; } } *frame_buf = buffers[queue_buf.index].start; *len = buffers[queue_buf.index].length; index = queue_buf.index; return 0; } int VideoDevice::unget_frame() { if(index != -1) { v4l2_buffer queue_buf; CLEAR(queue_buf); queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; queue_buf.memory = V4L2_MEMORY_MMAP; queue_buf.index = index; if(-1 == ioctl(fd, VIDIOC_QBUF, &queue_buf)) { emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno)))); return -1; } return 0; } return -1; }
======showmain.h文件======
#ifndef SHOWMAIN_H #define SHOWMAIN_H #include <QMainWindow> #include <QRect> #include <QTimer> #include <cv.h> #include <highgui.h> #include <QtGui> #include <QString> #include <QVector> #include "videodevice.h" #include <QImage> #include <QTime> namespace Ui { class ShowMain; } class ShowMain : public QMainWindow { Q_OBJECT public: explicit ShowMain(QWidget *parent = 0); ~ShowMain(); private: VideoDevice *vd; QPainter *painter; QLabel *label; QImage *frame; QImage *frame1; IplImage *cvimg; QTimer *timer; QTimer *timer1; uchar *pp; uchar * p; unsigned int len; int rs; public: int convert_yuv_to_rgb_pixel(int y, int u, int v); int convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height); private slots: void paintEvent1(); private: Ui::ShowMain *ui; }; #endif // SHOWMAIN_H
======showmain.cpp文件======
#include "showmain.h" #include "ui_showmain.h" extern "C" { #include <stdio.h> #include <stdlib.h> } using namespace std; ShowMain::ShowMain(QWidget *parent) : QMainWindow(parent), ui(new Ui::ShowMain) { ui->setupUi(this); pp = (unsigned char *)malloc(WIDTH * HEIGHT/*QWidget::width()*QWidget::height()*/* 4 * sizeof(char)); frame = new QImage(pp,WIDTH,HEIGHT,QImage::Format_RGB888); //此处必须使用rgb888格式 vd = new VideoDevice(tr("/dev/video0")); rs = vd->open_device(); if(-1==rs) { QMessageBox::warning(this,tr("error"),tr("open /dev/dsp error"),QMessageBox::Yes); vd->close_device(); } rs = vd->init_device(); if(-1==rs) { QMessageBox::warning(this,tr("error"),tr("init failed"),QMessageBox::Yes); vd->close_device(); } rs = vd->start_capturing(); if(-1==rs) { QMessageBox::warning(this,tr("error"),tr("start capture failed"),QMessageBox::Yes); vd->close_device(); } if(-1==rs) { QMessageBox::warning(this,tr("error"),tr("get frame failed"),QMessageBox::Yes); vd->stop_capturing(); } timer = new QTimer(this); connect(timer,SIGNAL(timeout()),this,SLOT(paintEvent1())); timer->start(30); } void ShowMain::paintEvent1() { rs = vd->get_frame((void **)&p,&len); rs = vd->get_frame((void **)&p,&len); convert_yuv_to_rgb_buffer(p,(unsigned char*)pp,WIDTH, HEIGHT); ui->label->setPixmap(QPixmap::fromImage(*frame,Qt::AutoColor)); rs = vd->unget_frame(); } //将yuyv转rgb888 int ShowMain::convert_yuv_to_rgb_buffer(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); pixel_24[1] = (pixel32 & 0x0000ff00) >> 8; pixel_24[2] = (pixel32 & 0x00ff0000) >> 16; 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); pixel_24[1] = (pixel32 & 0x0000ff00) >> 8; pixel_24[2] = (pixel32 & 0x00ff0000) >> 16; rgb[out++] = pixel_24[0]; rgb[out++] = pixel_24[1]; rgb[out++] = pixel_24[2]; } return 0; } int ShowMain::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; } ShowMain::~ShowMain() { delete ui; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。