作者:叁万英尺
转自:http://www.oschina.net/code/snippet_124925_3789
1. [文件] videodevice.h ~ 908B 下载(1683)
14 | #include <linux/videodev2.h> |
19 | #define CLEAR(x) memset(&(x), 0, sizeof(x)) |
21 | class VideoDevice :public QObject |
25 | VideoDevice(QString dev_name); |
33 | intget_frame(void **, size_t*); |
47 | unsigned int n_buffers; |
51 | voiddisplay_error(QString); |
55 | #endif // VIDEODEVICE_H |
2. [文件] videodevice.cpp ~ 7KB 下载(1487)
001 | #include "videodevice.h" |
003 | VideoDevice::VideoDevice(QString dev_name) |
005 | this->dev_name = dev_name; |
007 | this->buffers = NULL; |
013 | int VideoDevice::open_device() |
015 | fd = open(dev_name.toStdString().c_str(), O_RDWR, 0); |
020 | emit display_error(tr("open: %1").arg(QString(strerror(errno)))); |
026 | int VideoDevice::close_device() |
030 | emit display_error(tr("close: %1").arg(QString(strerror(errno)))); |
036 | int VideoDevice::init_device() |
039 | v4l2_cropcap cropcap; |
043 | if(-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap)) |
047 | emit display_error(tr("%1 is no V4l2 device").arg(dev_name)); |
051 | emit display_error(tr("VIDIOC_QUERYCAP: %1").arg(QString(strerror(errno)))); |
056 | if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) |
058 | emit display_error(tr("%1 is no video capture device").arg(dev_name)); |
062 | if(!(cap.capabilities & V4L2_CAP_STREAMING)) |
064 | emit display_error(tr("%1 does not support streaming i/o").arg(dev_name)); |
070 | cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
072 | if(0 == ioctl(fd, VIDIOC_CROPCAP, &cropcap)) |
075 | crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
076 | crop.c = cropcap.defrect; |
078 | if(-1 == ioctl(fd, VIDIOC_S_CROP, &crop)) |
086 | emit display_error(tr("VIDIOC_S_CROP: %1").arg(QString(strerror(errno)))); |
093 | emit display_error(tr("VIDIOC_CROPCAP: %1").arg(QString(strerror(errno)))); |
099 | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
100 | fmt.fmt.pix.width = 640; |
101 | fmt.fmt.pix.height = 480; |
102 | fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; |
103 | fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; |
105 | if(-1 == ioctl(fd, VIDIOC_S_FMT, &fmt)) |
107 | emit display_error(tr("VIDIOC_S_FMT").arg(QString(strerror(errno)))); |
111 | if(-1 == init_mmap()) |
119 | int VideoDevice::init_mmap() |
121 | v4l2_requestbuffers req; |
125 | req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
126 | req.memory = V4L2_MEMORY_MMAP; |
128 | if(-1 == ioctl(fd, VIDIOC_REQBUFS, &req)) |
132 | emit display_error(tr("%1 does not support memory mapping").arg(dev_name)); |
137 | emit display_error(tr("VIDIOC_REQBUFS %1").arg(QString(strerror(errno)))); |
144 | emit display_error(tr("Insufficient buffer memory on %1").arg(dev_name)); |
148 | buffers = (buffer*)calloc(req.count,sizeof(*buffers)); |
152 | emit display_error(tr("out of memory")); |
156 | for(n_buffers = 0; n_buffers < req.count; ++n_buffers) |
161 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
162 | buf.memory = V4L2_MEMORY_MMAP; |
163 | buf.index = n_buffers; |
165 | if(-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf)) |
167 | emit display_error(tr("VIDIOC_QUERYBUF: %1").arg(QString(strerror(errno)))); |
171 | buffers[n_buffers].length = buf.length; |
172 | buffers[n_buffers].start = |
175 | PROT_READ | PROT_WRITE, |
179 | if(MAP_FAILED == buffers[n_buffers].start) |
181 | emit display_error(tr("mmap %1").arg(QString(strerror(errno)))); |
189 | int VideoDevice::start_capturing() |
192 | for(i = 0; i < n_buffers; ++i) |
197 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
198 | buf.memory =V4L2_MEMORY_MMAP; |
202 | if(-1 == ioctl(fd, VIDIOC_QBUF, &buf)) |
204 | emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno)))); |
210 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
212 | if(-1 == ioctl(fd, VIDIOC_STREAMON, &type)) |
214 | emit display_error(tr("VIDIOC_STREAMON: %1").arg(QString(strerror(errno)))); |
220 | int VideoDevice::stop_capturing() |
223 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
225 | if(-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) |
227 | emit display_error(tr("VIDIOC_STREAMOFF: %1").arg(QString(strerror(errno)))); |
233 | int VideoDevice::uninit_device() |
236 | for(i = 0; i < n_buffers; ++i) |
238 | if(-1 == munmap(buffers[i].start, buffers[i].length)) |
240 | emit display_error(tr("munmap: %1").arg(QString(strerror(errno)))); |
249 | int VideoDevice::get_frame(void**frame_buf, size_t* len) |
251 | v4l2_buffer queue_buf; |
254 | queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
255 | queue_buf.memory = V4L2_MEMORY_MMAP; |
257 | if(-1 == ioctl(fd, VIDIOC_DQBUF, &queue_buf)) |
267 | emit display_error(tr("VIDIOC_DQBUF: %1").arg(QString(strerror(errno)))); |
272 | *frame_buf = buffers[queue_buf.index].start; |
273 | *len = buffers[queue_buf.index].length; |
274 | index = queue_buf.index; |
280 | int VideoDevice::unget_frame() |
284 | v4l2_buffer queue_buf; |
287 | queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
288 | queue_buf.memory = V4L2_MEMORY_MMAP; |
289 | queue_buf.index = index; |
291 | if(-1 == ioctl(fd, VIDIOC_QBUF, &queue_buf)) |
293 | emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno)))); |
3. [文件] processImage.h ~ 677B 下载(1412)
05 | #include "videodevice.h" |
07 | class ProcessImage :public QWidget |
11 | ProcessImage(QWidget *parent=0); |
24 | intconvert_yuv_to_rgb_pixel(inty, int u, int v); |
25 | intconvert_yuv_to_rgb_buffer(unsigned char*yuv, unsigned char *rgb, unsigned int width, unsignedint height); |
29 | voidpaintEvent(QPaintEvent *); |
30 | voiddisplay_error(QString err); |
4. [文件] processImage.cpp ~ 4KB 下载(1422)
002 | #include "processImage.h" |
003 | #include "videodevice.h" |
009 | ProcessImage::ProcessImage(QWidget *parent):QWidget(parent) |
011 | pp = (unsignedchar *)malloc(640 * 480* 3 *sizeof(char)); |
012 | painter =new QPainter(this); |
013 | frame = new QImage(pp,640,480,QImage::Format_RGB888); |
015 | label = new QLabel(); |
016 | vd = new VideoDevice(tr("/dev/video0")); |
018 | connect(vd, SIGNAL(display_error(QString)),this,SLOT(display_error(QString))); |
019 | rs = vd->open_device(); |
022 | QMessageBox::warning(this,tr("error"),tr("open /dev/dsp error"),QMessageBox::Yes); |
026 | rs = vd->init_device(); |
029 | QMessageBox::warning(this,tr("error"),tr("init failed"),QMessageBox::Yes); |
033 | rs = vd->start_capturing(); |
036 | QMessageBox::warning(this,tr("error"),tr("start capture failed"),QMessageBox::Yes); |
042 | QMessageBox::warning(this,tr("error"),tr("get frame failed"),QMessageBox::Yes); |
043 | vd->stop_capturing(); |
046 | timer = new QTimer(this); |
047 | connect(timer,SIGNAL(timeout()),this,SLOT(update())); |
050 | QHBoxLayout *hLayout =new QHBoxLayout(); |
051 | hLayout->addWidget(label); |
053 | setWindowTitle(tr("Capture")); |
056 | ProcessImage::~ProcessImage() |
058 | rs = vd->stop_capturing(); |
059 | rs = vd->uninit_device(); |
060 | rs = vd->close_device(); |
063 | void ProcessImage::paintEvent(QPaintEvent *) |
065 | rs = vd->get_frame((void**)&p,&len); |
066 | convert_yuv_to_rgb_buffer(p,pp,640,480); |
067 | frame->loadFromData((uchar *)pp,640 * 480 * 3 *sizeof(char)); |
075 | label->setPixmap(QPixmap::fromImage(*frame,Qt::AutoColor)); |
077 | rs = vd->unget_frame(); |
088 | void ProcessImage::display_error(QString err) |
090 | QMessageBox::warning(this,tr("error"), err,QMessageBox::Yes); |
094 | int ProcessImage::convert_yuv_to_rgb_buffer(unsignedchar *yuv, unsigned char *rgb, unsigned intwidth, unsigned int height) |
096 | unsigned int in, out = 0; |
097 | unsigned int pixel_16; |
098 | unsigned char pixel_24[3]; |
099 | unsigned int pixel32; |
101 | for(in = 0; in < width * height * 2; in += 4) { |
107 | y0 = (pixel_16 & 0x000000ff); |
108 | u = (pixel_16 & 0x0000ff00) >> 8; |
109 | y1 = (pixel_16 & 0x00ff0000) >> 16; |
110 | v = (pixel_16 & 0xff000000) >> 24; |
111 | pixel32 = convert_yuv_to_rgb_pixel(y0, u, v); |
112 | pixel_24[0] = (pixel32 & 0x000000ff); |
113 | pixel_24[1] = (pixel32 & 0x0000ff00) >> 8; |
114 | pixel_24[2] = (pixel32 & 0x00ff0000) >> 16; |
115 | rgb[out++] = pixel_24[0]; |
116 | rgb[out++] = pixel_24[1]; |
117 | rgb[out++] = pixel_24[2]; |
118 | pixel32 = convert_yuv_to_rgb_pixel(y1, u, v); |
119 | pixel_24[0] = (pixel32 & 0x000000ff); |
120 | pixel_24[1] = (pixel32 & 0x0000ff00) >> 8; |
121 | pixel_24[2] = (pixel32 & 0x00ff0000) >> 16; |
122 | rgb[out++] = pixel_24[0]; |
123 | rgb[out++] = pixel_24[1]; |
124 | rgb[out++] = pixel_24[2]; |
129 | int ProcessImage::convert_yuv_to_rgb_pixel(inty, int u, int v) |
131 | unsigned int pixel32 = 0; |
132 | unsigned char *pixel = (unsigned char *)&pixel32; |
134 | r = y + (1.370705 * (v-128)); |
135 | g = y - (0.698001 * (v-128)) - (0.337633 * (u-128)); |
136 | b = y + (1.732446 * (u-128)); |
143 | pixel[0] = r * 220 / 256; |
144 | pixel[1] = g * 220 / 256; |
145 | pixel[2] = b * 220 / 256; |
5. [文件] main.cpp ~ 212B 下载(1410)
02 | #include "processImage.h" |
04 | int main(intargc,char *argv[]) |
06 | QApplication app(argc,argv); |
08 | process.resize(640,480); |