int fd = open ("/dev/video",O_RDONLY)
if (fd==-1){
perror ("Can't open device")
return -1
}
/* 查询设备的输出格式 */
struct v4l2_format format
memset (&format,0,sizoef(format))
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE
if (-1==ioctl(fd,VIDIOC_G_FMT,&format)){
perror ("While getting format")
return -2
}
/*
* 这里要将struct v4l2_format结构体置零,然后将
* format.type设定为V4L2_BUF_TYPE_VIDEO_CAPTURE,
* 这样在进行 VIDIOC_G_FMT 的ioctl时,驱动就会知
* 道是在捕获视频的情形下获取格式的内容。
* 成功返回后,format就含有捕获视频的尺寸大小及格
* 式。格式存储在 format.fmt.pix.pixelformat这个32
* 位的无符号整数中,共四个字节,以小头序存储。这里
* 介绍一种获取的方法。
*/
char code[5]
unsigned int i
for (i=0i<4i++) {
code[i] = (format.fmt.pix.pixelformat &(0xff<<i*8))>>i*8
}
code[4]=0
/* 现在的code是一个以\0结束的字符串。很多摄像头都是以格式MJPG输出视频的。
* MJPG是Motion JPEG的缩写,其实就是一些没填霍夫曼表的JPEG图片。
*/
/* 请求一定数量的缓冲区。
* 但是不一定能请求到那么多。据体还得看返回的数量
*/
struct v4l2_requestbuffers req
memset (&req,0,sizeof(req))
req.count = 10
req.type= V4L2_BUF_TYPE_VIDEO_CAPTURE
req.memory = V4L2_MEMORY_MMAP
if (-1==ioctl(fd,VIDIOC_REQBUFS,&req)){
perror ("While requesting buffers")
return -3
}
if (req.count <5){
fprintf (stderr, "Can't get enough buffers!\n")
return -4
}
/* 这里请求了10块缓存区,并将其类型设为MMAP型。 */
/* 获取缓冲区的信息
* 在 *** 作之前,我们必须要能记录下我们
* 申请的缓存区,并在最后使用munmap释放它们
* 这里使用结构体
* struct buffer {
* void * start
* ssize_t length
* } 以及buffer数量
* static int nbuffer
* 来表示
*/
struct buffer * buffers = (struct buffer *)malloc (nbuffer*sizeof(*buffers))
if (!buffers){
perror ("Can't allocate memory for buffers!")
return -4
}
struct v4l2_buffer buf
for (nbuffer=0nbuffer<req.count++nbuffer) {
memset (&buf,0,sizeof(buf))
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE
buf.memory = V4L2_MEMORY_MMAP
buf.index= nbuffer
if (-1==ioctl(fd,VIDIOC_QUERYBUF,&buf)){
perror ("While querying buffer")
return -5
}
buffers[nbuffer].length = buf.length
buffers[nbuffer].start = mmap (
NULL,
buf.length,
PROT_READ, /* 官方文档说要加上PROT_WRITE,但加上会出错 */
MAP_SHARED,
fd,
buf.m.offset
)
if (MAP_FAILED == buffers[nbuffer].start) {
perror ("While mapping memory")
return -6
}
}
/*这个循环完成后,所有缓存区都保存在
*了buffers这个数组里了,完了就再将它们munmap即可。
*/
/* 打开视频捕获 */
enum v4l2_buf_type type
type = V4L2_BUF_TYPE_VIDEO_CAPTURE
if (-1==ioctl(fd,VIDIOC_STREAMON,&type)){
perror ("While opening stream")
return -7
}
/* 与内核交换缓冲区 */
unsigned int i
i=0
while(1) {
memset (&buf,0,sizeof(buf))
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE
buf.memory = V4L2_MEMORY_MMAP
buf.index = i
if (-1==ioctl(fd,VIDIOC_DQBUF,&buf)){
perror ("While getting buffer's data")
return -8
}
/* 现在就得到了一片缓冲区的数据,发送处理 */
process_image ( buffers+buf.index,buf.index )
/* 将缓冲区交还给内核 */
if (-1==ioctl(fd,VIDIOC_QBUF,&buf)){
perror ("While returning buffer's data")
return -9
}
i = (i+1) &nbuffer
}
这就是所有获取的过程了。至于图像的处理,则是由解码函数和Qt来处理。现在先进行一些思路的设计。设想在进行图像的转换时,必须提供一块内存区域来进行,我们当然可以在转换时使用malloc来进行动态分配,转换完成并显示后,再将它free。然而这样做对内核而言是一个不小的负担:每次为一整张图片分配内存,最少也有上百KB,如此大的分配量和释放量,很容易造成内存碎片加重内核的负担。由于仅是每转换一次才显示一次图像,所以这片用于转换的内存区域可以安全地复用,不会同时由两个线程 *** 作之。因此在初始化时我们为每一块内存映射缓冲区分配一块内存区域作为转换用。对于MJPEG到JPEG的转换,使用相同的内存大小。代码就不在此列出了。这片假设这个内存区域的起始指针为convertion_buffers,在process_image (struct buffer * buf, int index ) 中,有
void process_image (struct buffer *buf, int index){
struct * buffer conv_buf = convertion_buffers+index
do_image_conversion (
buf->start, buf->length, /* 要转换的区域 */
conv_buf->start, conv_buf->length, /* 保存转换数据的区域 */
)
/* 现在就可以把数据取出并交给QPixmap处理
* 要在一个QWidget里作图,必须重载paintEvent
* 函数并用QPainter作画。然而paintEvent
* 是由事件驱动层调用的,我们不能手工,
* 所以在我们自己的的重载类里要保存一个全局
* 的QPixmap。这里设为 QPixmap * m_pixmap
*/
m_pixmap ->loadFromData (conv_buf->start,conv_buf->length)
/* 立即安排一次重绘事件 */
repaint ()
}
/* 重载的paintEvent示例 */
MyWidget::paintEvent (QPaintEvent * evt) {
QPainter painter(this)
painter.drawPixmap (QPoint(0,0),*m_pixmap)
QWidget::paintEvent(evt)
}
V4L搞定 +QT显示摄像头视频 +QT显示GIF动画 2009-11-02 09:32 哎 两星期前终于搞定了qt上显示摄像头视频采集 现在来把最终重要的代码总结下 QImage imgunsigned char *bit= v4l _dev.buffer/ /v41_dev.buffer为内存映射的地址 QRgb *pointint r, g, bQPainter paintif(img.create(MAX_WIDTH, MAX_HEIGHT,32, 0, QImage::IgnoreEndian)) { for(y=0ysetMovie(movie)gif_lable->show()
哎 两星期前终于搞定了qt上显示摄像头视频采集, 现在来把最终重要的代码总结下
QImage img
unsigned char *bit= v4l _dev.buffer / //v41_dev.buffer为内存映射的地址
QRgb *point
int r, g, b
QPainter paint
if(img.create(MAX_WIDTH, MAX_HEIGHT,32, 0, QImage::IgnoreEndian))
{
for(y=0y<MAX_HEIGHTy++)
{
for(x=0x<MAX_WIDTHx++)
{
r=(int)bit[i+2]
g=(int)bit[i+1]
b=(int)bit[i]
point= (QRgb *)(img).scanLine(y)+ x
*point = qRgb(r,g,b) //qRgb函数能够将数据转为RGB三像素值
i+=3
}
}
}
但是不是很明白,希望有人能把这个直接写成 QT GUI APPLICATION PROJECT 然后我再参考下。。。因为对于QT的类库真的不太了解,呵呵
qt
abbr.(书写形式)夸脱。
Software Design of Wireless Order System Based on Qt and ARM.
基于Qt和ARM的无线点菜系统软件设计。
The development of embedded control interface based on Qt/ Embedded.
基于Qt/Embedded的嵌入式控制界面开发。
Development of software PLC development system based on Qt' components in Linux environment.
Linux环境下基于Qt库的软件PLC开发系统。
Design of the Embedded Linux Application Program Based on Qt/ Embedded.
基于Qt/Embedded的嵌入式Linux应用程序的设计。
Image processing interface development of qt/ embedded based on Embedded Linux.
基于嵌入式Linux系统的Qt/Embedded图像处理界面开发。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)