作者:叁万英尺
转自: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 | int get_frame( void **, size_t *); |
47 | unsigned int n_buffers; |
51 | void display_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 | int convert_yuv_to_rgb_pixel( int y, int u, int v); |
25 | int convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height); |
29 | void paintEvent(QPaintEvent *); |
30 | void display_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 = (unsigned char *) 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(unsigned char *yuv, unsigned char *rgb, unsigned int width, 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( int y, 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( int argc, char *argv[]) |
06 | QApplication app(argc,argv); |
08 | process.resize(640,480); |