Linux下控制免驱USB摄像头的信息
来源:互联网 发布:天天炫舞抽坐骑软件 编辑:程序博客网 时间:2024/05/01 11:38
Linux下控制免驱USB摄像头的信息-支持arm
--霜之小刀(转载请注明作者)
若有问题,请联系邮箱:lihn1011@163.com
QQ:2279557541
其实在linux下获取摄像头信息非常的简单。(这里我说的是UVC的USB摄像头哈,也就是所谓的免驱摄像头)
另外我操作摄像头使用的是v4l2方式,linux系统自带,无需借助三方库,但是视频的显示使用的是QT使用了第三方库
一般来说也就下面几步。
1、打开摄像头
2、获取摄像头信息
3、设置摄像头信息
4、控制摄像头开始摄像
5、设置视频数据的内存映射
6、获取视频数据
7、将视频数据转换为界面能显示的数据
8、显示
首先摄像头相关的是1~6步骤,我这里分装了一个类,先上代码
camara.h
#ifndef CAMARA_H#define CAMARA_H#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <getopt.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/time.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <asm/types.h>#include <linux/videodev2.h>#include <string>#include <map>#include <vector>struct CamaraBuffer{void* m_start;unsigned int m_length;};class Camara{public: Camara(); bool OpenCamara(const std::string& dev_name); bool Init(const std::string& dev_name, int width, int height); void* GetVideo(); void FreeVideo();private: std::string m_camara_name; int m_camara_fd; struct v4l2_capability m_camara_info; std::map<int/*pixmapformat*/, std::pair<int/*type*/,std::string> > m_camara_format; std::vector<CamaraBuffer> m_buffer_list; struct v4l2_buffer m_current_buf;};#endif // CAMARA_Hcamara.cpp
#include "Camara.h"Camara::Camara():m_camara_fd(0){}bool Camara::OpenCamara(const std::string &dev_name){ //打开摄像头 int fd = open(dev_name.c_str(), O_RDWR,0); if(fd < 0) { printf("Camara Open Fiald:%d\r\n", fd); return false; } m_camara_fd = fd; m_camara_name = dev_name; return true;}struct buffer{void* start;unsigned int length;}*buffers;bool Camara::Init(const std::string &dev_name, int width, int height){ int ret; if(!OpenCamara(dev_name)) return false; //获取摄像头相关信息 if((ret = ioctl(m_camara_fd, VIDIOC_QUERYCAP, &m_camara_info))) { printf("Camara Info Read Faild:%d",ret); return false; } else { printf("Camara Info:\r\n"); printf(" driver:%s\r\n",m_camara_info.driver); printf(" card:%s\r\n", m_camara_info.card); printf(" bus_info:%s\r\n", m_camara_info.bus_info); printf(" version:%d\r\n", m_camara_info.version); if(m_camara_info.capabilities & V4L2_CAP_VIDEO_CAPTURE) printf(" support: VIDEO_CAPTURE\r\n"); if(m_camara_info.capabilities & V4L2_CAP_VIDEO_OUTPUT) printf(" support: VIDEO_OUTPUT\r\n"); if(m_camara_info.capabilities & V4L2_CAP_VIDEO_OVERLAY) printf(" support: VIDEO_OVERLAY\r\n"); if(m_camara_info.capabilities & V4L2_CAP_VBI_CAPTURE) printf(" support: VBI_CAPTURE\r\n"); if(m_camara_info.capabilities & V4L2_CAP_VBI_OUTPUT) printf(" support: VBI_OUTPUT\r\n"); if(m_camara_info.capabilities & V4L2_CAP_SLICED_VBI_CAPTURE) printf(" support: SLICED_VBI_CAPTURE\r\n"); if(m_camara_info.capabilities & V4L2_CAP_SLICED_VBI_OUTPUT) printf(" support: SLICED_VBI_OUTPUT\r\n"); if(m_camara_info.capabilities & V4L2_CAP_RDS_CAPTURE) printf(" support: RDS_CAPTURE\r\n"); if(m_camara_info.capabilities & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) printf(" support: VIDEO_OUTPUT_OVERLAY\r\n"); if(m_camara_info.capabilities & V4L2_CAP_HW_FREQ_SEEK) printf(" support: HW_FREQ_SEEK\r\n"); if(m_camara_info.capabilities & V4L2_CAP_RDS_OUTPUT) printf(" support: RDS_OUTPUT\r\n"); } //get support format struct v4l2_fmtdesc fmtdesc; fmtdesc.index=0; fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; m_camara_format.clear(); printf("Camara Format Support:\r\n"); while(ioctl(m_camara_fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1) { printf(" type:%d description:%s pixmapformat:%d\r\n",fmtdesc.type, fmtdesc.description, fmtdesc.pixelformat); m_camara_format[fmtdesc.pixelformat] = std::pair<int, std::string> (fmtdesc.type,(char*)fmtdesc.description); fmtdesc.index++; } printf("Set Camara Format:\r\n"); {//set format struct v4l2_format fmt; memset ( &fmt, 0, sizeof(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)0; if ( (ret = ioctl(m_camara_fd, VIDIOC_S_FMT, &fmt))) { printf("Set Camara Format faild:%d\r\n",ret); return -1; } } struct v4l2_format fmt; fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; printf("Camara Format Current:\r\n"); if((ret = ioctl(m_camara_fd,VIDIOC_G_FMT,&fmt))) { printf("Get Camara Format Faild:%d\r\n", ret); return false; } else { printf(" w:%d h:%d format:%s\r\n", fmt.fmt.pix.width, fmt.fmt.pix.height, m_camara_format[fmt.fmt.pix.pixelformat].second.c_str()); } //request buffer struct v4l2_requestbuffers req; req.count=8; req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory=V4L2_MEMORY_MMAP; printf("Request Buffer"); if((ret = ioctl(m_camara_fd,VIDIOC_REQBUFS,&req))) { printf("Request Buffer Faild:%d\r\n", ret); return false; } printf("Request Buffer Successful\r\n"); // printf("Query Buffer\r\n"); m_buffer_list.resize(req.count); for (unsigned int buffer_idx = 0; buffer_idx < req.count; ++buffer_idx) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type =V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory =V4L2_MEMORY_MMAP; buf.index =buffer_idx; // 查询序号为n_buffers 的缓冲区,得到其起始物理地址和大小 if ( (ret = ioctl(m_camara_fd, VIDIOC_QUERYBUF, &buf))) { printf("buffer query faild:%d\r\n", ret); return false; } m_buffer_list[buffer_idx].m_length= buf.length; // 映射内存 errno = 0; m_buffer_list[buffer_idx].m_start= (char*)mmap (NULL,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,m_camara_fd, buf.m.offset); if (MAP_FAILED == m_buffer_list[buffer_idx].m_start) { printf("mmap faild:%d,%s\r\n", ret,strerror(errno)); return false; } } printf("Query Buffer Successful\r\n"); //Set Buffer To Quene for (unsigned int i = 0; i< req.count; ++i) { struct v4l2_buffer buf; buf.type =V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory =V4L2_MEMORY_MMAP; buf.index = i; if((ret=ioctl (m_camara_fd, VIDIOC_QBUF, &buf))) { printf("Set Buffer To Quene faild:%d,%s\r\n", ret,strerror(errno)); return false; } } printf("Set Buffer To Quene Successful\r\n"); //Stream On int type =V4L2_BUF_TYPE_VIDEO_CAPTURE; if((ret = ioctl (m_camara_fd,VIDIOC_STREAMON, &type))) { printf("Stream On faild:%d,%s\r\n", ret,strerror(errno)); return false; } printf("Stream On Successful\r\n"); return true;}void *Camara::GetVideo(){ //void* video_ptr = 0; int ret; memset(&m_current_buf, 0, sizeof(m_current_buf)); m_current_buf.type =V4L2_BUF_TYPE_VIDEO_CAPTURE; m_current_buf.memory =V4L2_MEMORY_MMAP; // 从缓冲区取出一个缓冲帧 if((ret = ioctl (m_camara_fd,VIDIOC_DQBUF, &m_current_buf))) { printf("GetVideo faild:%d,%s\r\n", ret,strerror(errno)); return NULL; } // 图像处理 ; //video_ptr = malloc(m_buffer_list[buf.index].m_length); //memcpy(video_ptr, m_buffer_list[buf.index].m_start, m_buffer_list[buf.index].m_length); // 将取出的缓冲帧放回缓冲区 //printf("GetVideo Successful\r\n"); return m_buffer_list[m_current_buf.index].m_start;}void Camara::FreeVideo(){ int ret; if((ret = ioctl (m_camara_fd, VIDIOC_QBUF,&m_current_buf))) { printf("GetVideo faild:%d,%s\r\n", ret,strerror(errno)); //return NULL; }}这里面要注意一点,我们在代码中获取得到了摄像头的信息,主要是为了知道我们的摄像机到底支持哪些格式,然后在设置进去。如果格式不支持,那么我们设置的时候就会报错。
然后是视频的显示,我这里的界面库使用的是QT。
main.cpp
main.cpp
#include "MainWidget.h"#include <QApplication>#include "Camara.h"#include "MainWidget.h"int main(int argc, char *argv[]){ QApplication a(argc, argv); MainWidget w; w.setWindowFlags(Qt::FramelessWindowHint); w.show(); return a.exec();}
MainWidget.h
#ifndef MAINWIDGET_H#define MAINWIDGET_H#include <QWidget>#include <QTimer>#include "Camara.h"namespace Ui {class MainWidget;}class MainWidget : public QWidget{ Q_OBJECTpublic: explicit MainWidget(QWidget *parent = 0); ~MainWidget();protected: void paintEvent(QPaintEvent *event);private slots: void OnTimer();private: int m_video_width; int m_video_height; Ui::MainWidget *ui; Camara m_camara; QTimer m_paint_timer;};#endif // MAINWIDGET_H
MainWidget.cpp
#include "MainWidget.h"#include "ui_MainWidget.h"#include <QPainter>MainWidget::MainWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MainWidget),m_video_width(640),m_video_height(480){ ui->setupUi(this); m_camara.Init("/dev/video0",m_video_width, m_video_height); m_paint_timer.setInterval(50); connect(&m_paint_timer,SIGNAL(timeout()), this, SLOT(OnTimer()) ); m_paint_timer.start();}MainWidget::~MainWidget(){ delete ui;}int 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;}int 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;}#include <QDateTime>void MainWidget::paintEvent(QPaintEvent *event){ QPainter pt(this); QDateTime time = QDateTime::currentDateTime(); printf("%d:%d:%d:%d\r\n", time.time().hour(),time.time().minute(),time.time().second(),time.time().msec()); unsigned char* data = (unsigned char*)m_camara.GetVideo(); unsigned char* rgb24 = (unsigned char*)malloc(614400*2); QImage img(rgb24, m_video_width,m_video_height,QImage::Format_RGB888); convert_yuv_to_rgb_buffer(data,rgb24,m_video_width,m_video_height/*QWidget::width(),QWidget::height()*/); img.loadFromData((uchar *)rgb24,/*len*/320 * 240 * 3 * sizeof(char)); //scale img = img.scaled(640,480); pt.drawImage(0,0,img); m_camara.FreeVideo(); free(rgb24); time = QDateTime::currentDateTime(); printf("%d:%d:%d:%d\r\n", time.time().hour(),time.time().minute(),time.time().second(),time.time().msec());}void MainWidget::OnTimer(){ printf("ontimer\r\n"); update();}
0 0
- Linux下控制免驱USB摄像头的信息
- linux 下USB 摄像头的使用说明
- linux 下USB 摄像头的使用说明
- linux下开发USB摄像头
- LINUX 下USB摄像头设置
- ROS下获取USB免驱动高速摄像头图像数据
- 【servfox】Arm-linux下USB摄像头的视频服务器的实现
- Linux下基于XScale的USB摄像头图像采集
- Linux下基于XScale的USB摄像头图像采集
- linux下的V4L2提取USB摄像头图像(一)
- Arm-linux下USB摄像头的视频…
- Ehome:智能家居之基于USB摄像头免驱的视频采集服务器
- Linux系统下USB摄像头驱动开发
- Linux系统下USB摄像头驱动开发
- Linux系统下USB摄像头驱动开发
- Linux系统下USB摄像头驱动开发
- Linux系统下USB摄像头驱动开发
- ARM9+Linux下USB摄像头图像采集
- UVA-424 Integer Inquiry
- WINDOWS环境下通过Xmanger远程连接CENTOS图形桌面【转】
- 龟兔赛跑
- SQLI-LAB 的 实战记录(Less 11 - Less 20)
- servlet实现请求转发和请求重定向的特性与区别
- Linux下控制免驱USB摄像头的信息
- maven开发环境,写第一个HelloWorld
- JS修改CSS的三种方式
- UVA-156 Ananagrams
- Handler机制-----我的理解
- 树莓派GPIO的编号规范
- 【linux c】c语言十进制数转换为十六进制输出_学习笔记_005
- 类的加载与初始化
- 枚举