Linux 下用 QT 打开摄像头并显示

 
#ifndef VIDEODEVICE_H
02#define VIDEODEVICE_H
03  
04#include <string.h>
05#include <stdlib.h>
06#include <errno.h>
07#include <fcntl.h>
08  
09  
10#include <sys/ioctl.h>
11#include <sys/mman.h>
12  
13#include <asm/types.h>
14#include <linux/videodev2.h>
15  
16#include <QString>
17#include <QObject>
18  
19#define CLEAR(x) memset(&(x), 0, sizeof(x))
20  
21class VideoDevice : public QObject
22{
23    Q_OBJECT
24public:
25    VideoDevice(QString dev_name);
26    //VideoDevice();
27    intopen_device();
28    intclose_device();
29    intinit_device();
30    intstart_capturing();
31    intstop_capturing();
32    intuninit_device();
33    intget_frame(void**, size_t*);
34    intunget_frame();
35  
36private:
37    intinit_mmap();
38  
39    structbuffer
40    {
41        void* start;
42        size_tlength;
43    };
44    QString dev_name;
45    intfd;
46    buffer* buffers;
47    unsignedint n_buffers;
48    intindex;
49  
50signals:
51    voiddisplay_error(QString);
52  
53};
54  

55

#endif // VIDEODEVICE_H

 

#include "videodevice.h"

002  
003VideoDevice::VideoDevice(QString dev_name)
004{
005    this->dev_name = dev_name;
006    this->fd = -1;
007    this->buffers = NULL;
008    this->n_buffers = 0;
009    this->index = -1;
010  
011}
012  
013int VideoDevice::open_device()
014{
015    fd = open(dev_name.toStdString().c_str(), O_RDWR/*|O_NONBLOCK*/, 0);
016   // fd = open(dev_name.toStdString().c_str(), O_RDWR|O_NONBLOCK, 0);
017  
018    if(-1 == fd)
019    {
020        emit display_error(tr("open: %1").arg(QString(strerror(errno))));
021        return-1;
022    }
023    return0;
024}
025  
026int VideoDevice::close_device()
027{
028    if(-1 == close(fd))
029    {
030        emit display_error(tr("close: %1").arg(QString(strerror(errno))));
031        return-1;
032    }
033    return0;
034}
035  
036int VideoDevice::init_device()
037{
038    v4l2_capability cap;
039    v4l2_cropcap cropcap;
040    v4l2_crop crop;
041    v4l2_format fmt;
042  
043    if(-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap))
044    {
045        if(EINVAL ==errno)
046        {
047            emit display_error(tr("%1 is no V4l2 device").arg(dev_name));
048        }
049        else
050        {
051            emit display_error(tr("VIDIOC_QUERYCAP: %1").arg(QString(strerror(errno))));
052        }
053        return-1;
054    }
055  
056    if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
057    {
058        emit display_error(tr("%1 is no video capture device").arg(dev_name));
059        return-1;
060    }
061  
062    if(!(cap.capabilities & V4L2_CAP_STREAMING))
063    {
064        emit display_error(tr("%1 does not support streaming i/o").arg(dev_name));
065        return-1;
066    }
067  
068    CLEAR(cropcap);
069  
070    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
071  
072    if(0 == ioctl(fd, VIDIOC_CROPCAP, &cropcap))
073    {
074        CLEAR(crop);
075        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
076        crop.c = cropcap.defrect;
077  
078        if(-1 == ioctl(fd, VIDIOC_S_CROP, &crop))
079        {
080            if(EINVAL ==errno)
081            {
082//                emit display_error(tr("VIDIOC_S_CROP not supported"));
083            }
084            else
085            {
086                emit display_error(tr("VIDIOC_S_CROP: %1").arg(QString(strerror(errno))));
087                return-1;
088            }
089        }
090    }
091    else
092    {
093        emit display_error(tr("VIDIOC_CROPCAP: %1").arg(QString(strerror(errno))));
094        return-1;
095    }
096  
097    CLEAR(fmt);
098  
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;
104  
105    if(-1 == ioctl(fd, VIDIOC_S_FMT, &fmt))
106    {
107        emit display_error(tr("VIDIOC_S_FMT").arg(QString(strerror(errno))));
108        return-1;
109    }
110  
111    if(-1 == init_mmap())
112    {
113        return-1;
114    }
115  
116    return0;
117}
118  
119int VideoDevice::init_mmap()
120{
121    v4l2_requestbuffers req;
122    CLEAR(req);
123  
124    req.count = 4;
125    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
126    req.memory = V4L2_MEMORY_MMAP;
127  
128    if(-1 == ioctl(fd, VIDIOC_REQBUFS, &req))
129    {
130        if(EINVAL ==errno)
131        {
132            emit display_error(tr("%1 does not support memory mapping").arg(dev_name));
133            return-1;
134        }
135        else
136        {
137            emit display_error(tr("VIDIOC_REQBUFS %1").arg(QString(strerror(errno))));
138            return-1;
139        }
140    }
141  
142    if(req.count < 2)
143    {
144        emit display_error(tr("Insufficient buffer memory on %1").arg(dev_name));
145        return-1;
146    }
147  
148    buffers = (buffer*)calloc(req.count,sizeof(*buffers));
149  
150    if(!buffers)
151    {
152        emit display_error(tr("out of memory"));
153        return-1;
154    }
155  
156    for(n_buffers = 0; n_buffers < req.count; ++n_buffers)
157    {
158        v4l2_buffer buf;
159        CLEAR(buf);
160  
161        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
162        buf.memory = V4L2_MEMORY_MMAP;
163        buf.index = n_buffers;
164  
165        if(-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf))
166        {
167            emit display_error(tr("VIDIOC_QUERYBUF: %1").arg(QString(strerror(errno))));
168            return-1;
169        }
170  
171        buffers[n_buffers].length = buf.length;
172        buffers[n_buffers].start =
173                mmap(NULL,// start anywhere
174                     buf.length,
175                     PROT_READ | PROT_WRITE,
176                     MAP_SHARED,
177                     fd, buf.m.offset);
178  
179        if(MAP_FAILED == buffers[n_buffers].start)
180        {
181            emit display_error(tr("mmap %1").arg(QString(strerror(errno))));
182            return-1;
183        }
184    }
185    return0;
186  
187}
188  
189int VideoDevice::start_capturing()
190{
191    unsignedint i;
192    for(i = 0; i < n_buffers; ++i)
193    {
194        v4l2_buffer buf;
195        CLEAR(buf);
196  
197        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
198        buf.memory =V4L2_MEMORY_MMAP;
199        buf.index = i;
200//        fprintf(stderr, "n_buffers: %d\n", i);
201  
202        if(-1 == ioctl(fd, VIDIOC_QBUF, &buf))
203        {
204            emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno))));
205            return-1;
206        }
207    }
208  
209    v4l2_buf_type type;
210    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
211  
212    if(-1 == ioctl(fd, VIDIOC_STREAMON, &type))
213    {
214        emit display_error(tr("VIDIOC_STREAMON: %1").arg(QString(strerror(errno))));
215        return-1;
216    }
217    return0;
218}
219  
220int VideoDevice::stop_capturing()
221{
222    v4l2_buf_type type;
223    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
224  
225    if(-1 == ioctl(fd, VIDIOC_STREAMOFF, &type))
226    {
227        emit display_error(tr("VIDIOC_STREAMOFF: %1").arg(QString(strerror(errno))));
228        return-1;
229    }
230    return0;
231}
232  
233int VideoDevice::uninit_device()
234{
235    unsignedint i;
236    for(i = 0; i < n_buffers; ++i)
237    {
238        if(-1 == munmap(buffers[i].start, buffers[i].length))
239        {
240            emit display_error(tr("munmap: %1").arg(QString(strerror(errno))));
241            return-1;
242        }
243  
244    }
245    free(buffers);
246    return0;
247}
248  
249int VideoDevice::get_frame(void **frame_buf, size_t* len)
250{
251    v4l2_buffer queue_buf;
252    CLEAR(queue_buf);
253  
254    queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
255    queue_buf.memory = V4L2_MEMORY_MMAP;
256  
257    if(-1 == ioctl(fd, VIDIOC_DQBUF, &queue_buf))
258    {
259        switch(errno)
260        {
261        caseEAGAIN:
262//            perror("dqbuf");
263            return-1;
264        caseEIO:
265            return-1 ;
266        default:
267            emit display_error(tr("VIDIOC_DQBUF: %1").arg(QString(strerror(errno))));
268            return-1;
269        }
270    }
271  
272    *frame_buf = buffers[queue_buf.index].start;
273    *len = buffers[queue_buf.index].length;
274    index = queue_buf.index;
275  
276    return0;
277  
278}
279  
280int VideoDevice::unget_frame()
281{
282    if(index != -1)
283    {
284        v4l2_buffer queue_buf;
285        CLEAR(queue_buf);
286  
287        queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
288        queue_buf.memory = V4L2_MEMORY_MMAP;
289        queue_buf.index = index;
290  
291        if(-1 == ioctl(fd, VIDIOC_QBUF, &queue_buf))
292        {
293            emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno))));
294            return-1;
295        }
296        return0;
297    }
298    return-1;

}

http://www.oschina.net/code/snippet_124925_3789

 

http://hi.baidu.com/greatren518/blog/item/ede5db0112cb6d0a1c958328.html/cmtid/8475c1dedea97956ccbf1ad2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值