
- 第一章 QT中的容器--》跟C++容器的用法几乎一模一样
- 1.QT容器对比C++容器
- 第二章 QT中的摄像头显示
- 1.涉及到类
- 2.思路和步骤
- (1)获取当前系统中所有的摄像头信息
- (2)定义QCamera对象
- (3)准备好摄像头显示需要用到的窗口(创建QVideoWidget对象跟你在ui中拖过来的QWidget绑定在一起)
- (4)关闭摄像头
- 3.QT中的摄像头类和代码不能在ARM平台上运行
- 第三章 V4L2摄像头代码融入到QT工程中
- 1.思路
- 2.C++关键字
- 3.笔试题
- 第五章 jpeg库的移植和使用
- 1.libjpeg移植
- (1)解压jpeg的源码包,然后执行configure
- 2.使用jpeg库提供的接口函数显示jpg图片
- 3.显示思路
- 第四章 源码编写和注释
- 【1】QT中的摄像头显示
- main.cpp
- mainwindow.h
- mainwindow.cpp
- mainwindow.ui
- 【2】任意位置显示任意大小的jpg
- showjpg.c
- JPG库和相关头文件
- explicit的作用.cpp
- 逗号表达式.c
- 【3】用定时器实现V4L2摄像头显示
- main.cpp
- mainwindow.h
- mainwindow.cpp
- mainwindow.ui
- moc_mainwindow.cpp
- moc_mycamera.cpp
- mycamera.h
- mycamera.cpp
- ui_mainwindow.h
- 【4】用多线程实现V4L2摄像头显示
- mian.c
- mainwindow.h
- mainwindow.cpp
- mainwindow.ui
- moc_mainwindow.cpp
- moc_mycamera.cpp
- mycamera.h
- mycamera.cpp
- ui_mainwindow.h
- 第五章 往期内容回顾
vector QVector
set QSet
list QList
map QMap
stack QStack
queue QQueue
第二章 QT中的摄像头显示
1.涉及到类
QT += multimedia
QT += multimediawidgets
QCameraInfo //获取当前系统所有的摄像头信息
QCamera //表示摄像头对象
QVideoWidget //表示摄像头拍摄画面的显示窗口
2.思路和步骤
(1)获取当前系统中所有的摄像头信息
[static] QList<QCameraInfo> QCameraInfo::availableCameras()
返回值:容器,存放了所有的摄像头信息
QString QCameraInfo::description() const
返回值:摄像头的描述信息
QString QCameraInfo::deviceName() const
返回值:摄像头的设备名称
(2)定义QCamera对象
QCamera::QCamera(const QByteArray &deviceName)
参数:依据摄像头的设备名字构造一个摄像头对象
(3)准备好摄像头显示需要用到的窗口(创建QVideoWidget对象跟你在ui中拖过来的QWidget绑定在一起)
QVideoWidget::QVideoWidget(QWidget *parent = nullptr)
参数:parent --》把你在ui中拖过来的QWidget对象作为实参
把摄像头跟窗口也绑定
void QCamera::setViewfinder(QVideoWidget *viewfinder)
参数:viewfinder--》你刚才准备好的那个窗口
调整窗口的大小,让窗口给QWidget大小保持一致
void QWidget::resize(int w, int h)
显示窗口
void QWidget::show()
启动摄像头
void QCamera::start()
(4)关闭摄像头
void QCamera::stop()
3.QT中的摄像头类和代码不能在ARM平台上运行
原因:QT的摄像头类不支持V4L2架构
第三章 V4L2摄像头代码融入到QT工程中项目阶段(在开发板上运行):需要用到摄像头
1.思路跟QT控制硬件的思路类似,把摄像头代码(C语言)改写成C++(封装成C++的一个类)
2.C++关键字explicit //禁止隐式转换
父类指针=子类对象的地址
int a=1;
int b=0;
int c=(a,b++); // (a,b++)逗号表达式,从左到右计算,最终式子的结果由最右边的式子决定
./configure --prefix=/home/gec/xxx CC=arm-linux-gcc --host=arm-linux --enable-shared --enable-static
--prefix 指定编译得到的库文件,头文件所在的位置
--enable-shared 生成动态库
--enable-static 生成静态库
执行:
make && make install
make 编译库
make install 把编译产生的库文件头文件安装到第一步你指定的目录下
2.使用jpeg库提供的接口函数显示jpg图片
jpg图片的背景知识:jpg图片采用特殊的算法压缩过,占用的存储空间很小,很适合在网络上传输
大致思路:jpg原始数据还原出来(解压缩) --》得到原始的RGB数据–》原始的RGB转换成ARGB填充到开发板的LCD液晶显示屏上
第一步:定义解压缩结构体变量和处理错误的结构体变量,并初始化
struct jpeg_decompress_struct 解压缩结构体
{
image_width; //图片宽
image_height; //图片高
num_components; //图片的色深(3个字节),每个像素点占用的字节数
err; //保存jpeg_std_error()返回值
}
jpeg_create_decompress(cinfo)
参数: cinfo --》解压缩结构体指针
struct jpeg_error_mgr 处理错误的结构体
{
}
jpeg_std_error(struct jpeg_error_mgr * err);
参数:err --》保持错误信息的结构体指针
第二步:指定解压缩数据源
fopen(你要显示的那张jpg图片)
jpeg_stdio_src(j_decompress_ptr cinfo, FILE * infile);
参数:cinfo --》解压缩结构体指针
infile --》你刚才打开的那张图片
第三步:读取jpg图片的头信息
jpeg_read_header(j_decompress_ptr cinfo,boolean require_image)
参数:cinfo --》解压缩结构体指针
require_image --》true
第四步:开始解压缩得到jpg原始的RGB数据
jpeg_start_decompress(j_decompress_ptr cinfo);
参数:cinfo --》解压缩结构体指针
第五步:关键步骤,读取解压缩得到的RGB数据,把数据填充到开发板的lcd上
jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines,JDIMENSION max_lines)
参数:cinfo --》解压缩结构体指针
scanlines --》存放读取到解压缩后的RGB数据
max_lines --》你读取多少行RGB数据,一般一次读取一行
char *buf=malloc(一行RGB数据大小);
for(i=0; i<图片高; i++)
{
jpeg_read_scanlines(&mydem,&buf,1); //一次读取一行
//立马把buf中的一行RGB数据填充到开发板的lcd上
}
第六步:收尾
jpeg_finish_decompress(j_decompress_ptr cinfo);
jpeg_destroy_decompress(j_decompress_ptr cinfo);
第四章 源码编写和注释
【1】QT中的摄像头显示
main.cpp
#include "mainwindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_comboBox_activated(const QString &arg1);
void on_closebt_clicked();
private:
Ui::MainWindow *ui;
QCamera *cam;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
//获取当前系统摄像头信息
void MainWindow::on_pushButton_clicked()
{
QList<QCameraInfo> mylist=QCameraInfo::availableCameras();
//把摄像头的信息在下拉框中显示出来
for(auto &x:mylist)
{
//qDebug()<<"摄像头的描述信息是: "<
//qDebug()<<"摄像头的设备名称是: "<
//在下拉框中显示设备名字
ui->comboBox->addItem(x.deviceName());
}
}
//点击下拉框中的某个摄像头名称,启动摄像头
void MainWindow::on_comboBox_activated(const QString &arg1)
{
//创建摄像头对象
cam=new QCamera(arg1.toUtf8());
//准备好摄像头显示需要用到的窗口
QVideoWidget *win=new QVideoWidget(ui->widget);
//把摄像头跟窗口绑定在一起
cam->setViewfinder(win);
//调整窗口大小
win->resize(ui->widget->width(),ui->widget->height());
//显示窗口
win->show();
//启动摄像头
cam->start();
}
//关闭摄像头
void MainWindow::on_closebt_clicked()
{
cam->stop();
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>251</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>获取当前系统摄像头信息</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>251</width>
<height>51</height>
</rect>
</property>
</widget>
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>280</x>
<y>10</y>
<width>511</width>
<height>521</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="closebt">
<property name="geometry">
<rect>
<x>10</x>
<y>230</y>
<width>171</width>
<height>131</height>
</rect>
</property>
<property name="text">
<string>关闭摄像头</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
界面设计:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "jpeglib.h" //jpg库的头文件
// 封装任意位置显示任意大小的jpg图片
int show_anyjpg(int x,int y,char *jpgpath)
{
int i,j,k;
int lcdfd;
int *lcdmem;
//打开lcd
lcdfd=open("/dev/fb0",O_RDWR);
if(lcdfd==-1)
{
perror("打开lcd失败!\n");
return -1;
}
//映射得到lcd的首地址
lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
if(lcdmem==NULL)
{
perror("映射lcd失败了!\n");
return -1;
}
//定义解压缩结构体变量和处理错误的结构体变量,并初始化
struct jpeg_decompress_struct mydem;
jpeg_create_decompress(&mydem);
struct jpeg_error_mgr myerr;
mydem.err=jpeg_std_error(&myerr);
//指定解压缩数据源
FILE *myfile=fopen(jpgpath,"r+");
if(myfile==NULL)
{
perror("打开jpg失败!\n");
return -1;
}
jpeg_stdio_src(&mydem,myfile);
//读取文件头
jpeg_read_header(&mydem,true);
//开始解压缩得到jpg原始的RGB数据
jpeg_start_decompress(&mydem);
printf("宽: %d\n",mydem.image_width);
printf("高: %d\n",mydem.image_height);
printf("色深: %d\n",mydem.num_components);
//定义指针存放一行RGB数据
char *buf=malloc(3*mydem.image_width);
//定义数组存放转换得到的ARGB数据
int otherbuf[mydem.image_width];
//循环读取解压缩得到的数据,填充到lcd
for(i=0; i<mydem.image_height; i++)
{
jpeg_read_scanlines(&mydem,(JSAMPARRAY)&buf,1);
//读取RGB--》ARGB buf[0]--[2] 一组RGB
for(j=0,k=0; k<mydem.image_width; j+=3,k++)
otherbuf[k]=0x00<<24|buf[j]<<16|buf[j+1]<<8|buf[j+2];
//*(lcdmem+偏移量)=0x00<<24|buf[j]<<16|buf[j+1]<<8|buf[j+2]; 更加简洁的写法
//把otherbuf填充到lcd上,从(x,y)位置开始
memcpy(lcdmem+800*(y+i)+x,&otherbuf[0],4*mydem.image_width);
}
//收尾
jpeg_finish_decompress(&mydem);
jpeg_destroy_decompress(&mydem);
fclose(myfile);
close(lcdfd);
munmap(lcdmem,800*480*4);
free(buf);
return 0;
}
int main(int argc,char **argv)
{
show_anyjpg(100,205,argv[1]);
}
JPG库和相关头文件
include/目录下:
由于内容繁多并且文件较大,大家wp自取,永久有效
#include
using namespace std;
class Animal
{
public:
explicit Animal(int age)
{
cout<<"我是动物 年龄: "<<age<<endl;
}
};
int main()
{
Animal a1(7);
//Animal a2=5; //错误,隐式转换
}
逗号表达式.c
#include
int main()
{
//int a=1;
//int b=0;
//int c=(a,b++);
//printf("%d %d %d\n",a,b,c);
int a=1;
int b=2;
int c=a++; // c=0 a=26 b=3 d 26
int d=(a+b,b++,c--,a+=7,a*=b,--a); //挖坑
//1 2 1 0
//9 3 1 0
//27 2 1 26
printf("%d %d %d %d\n",a,b,c,d);
}
【3】用定时器实现V4L2摄像头显示
main.cpp
#include "mainwindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include "mycamera.h"
#include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_startbt_clicked();
void on_closebt_clicked();
void fun();
private:
Ui::MainWindow *ui;
mycamera cam;
QTimer mytimer;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//构造函数中初始化摄像头
cam.camera_init();
//设置定时时间
mytimer.setInterval(50);
//关联timeout信号
connect(&mytimer,SIGNAL(timeout()),this,SLOT(fun()));
}
MainWindow::~MainWindow()
{
//在析构函数中关闭摄像头
cam.camera_uninit();
delete ui;
}
//启动摄像头(实际上是启动定时器,在定时器中不断地捕捉画面)
void MainWindow::on_startbt_clicked()
{
mytimer.start();
}
//关闭摄像头(实际上是关闭定时器)
void MainWindow::on_closebt_clicked()
{
mytimer.stop();
}
//跟定时器超时对应的槽函数
void MainWindow::fun()
{
cam.camera_capture();
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="startbt">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>80</width>
<height>480</height>
</rect>
</property>
<property name="text">
<string>启动</string>
</property>
</widget>
<widget class="QPushButton" name="closebt">
<property name="geometry">
<rect>
<x>720</x>
<y>0</y>
<width>80</width>
<height>480</height>
</rect>
</property>
<property name="text">
<string>关闭</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>80</x>
<y>0</y>
<width>640</width>
<height>480</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 0, 0);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
界面设计:
/****************************************************************************
** Meta object code from reading C++ file 'mainwindow.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include "mainwindow.h"
#include
#include
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'mainwindow.h' doesn't include ."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.7.0. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
QT_BEGIN_MOC_NAMESPACE
struct qt_meta_stringdata_MainWindow_t {
QByteArrayData data[5];
char stringdata0[54];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_MainWindow_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
{
QT_MOC_LITERAL(0, 0, 10), // "MainWindow"
QT_MOC_LITERAL(1, 11, 18), // "on_startbt_clicked"
QT_MOC_LITERAL(2, 30, 0), // ""
QT_MOC_LITERAL(3, 31, 18), // "on_closebt_clicked"
QT_MOC_LITERAL(4, 50, 3) // "fun"
},
"MainWindow"on_closebt_clicked}fun"on_startbt_clicked;#"
undef
QT_MOC_LITERALstatic
const[ ]
= // content: uint qt_meta_data_MainWindow7, // revision {
0
,// classname 0
,0 ,
// classinfo3 ,14 ,
// methods0 ,0 ,
// properties0 ,0 ,
// enums/sets0 ,0 ,
// constructors0 ,// flags 0
,// signalCount // slots: name, argc, parameters, tag, flags
1, 0
,
29, 2, 0x08/* Private */ ,3 , 0,
30, 2, 0x08/* Private */ ,4 , 0,
31, 2, 0x08/* Private */ ,// slots: parameters :: ,::
,
QMetaType::Void,
QMetaType0Void// eod
QMetaType}Void;
void MainWindow
::qt_static_metacall
( *,::,QObject int_o, QMetaObjectvoidCall _c* * _id) if (==_a::
{
) *_c = QMetaObjectstatic_castInvokeMetaMethod< {
MainWindow *_t ( );MainWindow Q_UNUSED>(_o)switch
()_tcase
0 :_idon_startbt_clicked {
( ); _t->break;case1 :on_closebt_clicked
( ); _t->break;case2 :fun
( ); _t->break;default: ;}
}Q_UNUSED (
)
;
}const_a::=
&
:: QMetaObject MainWindow,staticMetaObject . {
{ ,QMainWindow,staticMetaObject, qt_meta_stringdata_MainWindow,data}
qt_meta_data_MainWindow} qt_static_metacall; Q_NULLPTRconst Q_NULLPTR*
MainWindow::
metaObject QMetaObject ()constreturn::? ::
{
dynamicMetaObject QObject(d_ptr->metaObject ) QObject:d_ptr->&;} void *staticMetaObjectMainWindow
::
qt_metacast (constchar*)if ( !_clname)
{
return ;if_clname( ! Q_NULLPTRstrcmp
( ,.))_clnamereturn qt_meta_stringdata_MainWindowstatic_caststringdata0<void
* (const_cast<*>(this) MainWindow)>;returnQMainWindow::qt_metacast
( );}int_clnameMainWindow::
qt_metacall
( ::,int,QMetaObjectvoidCall _c* * _id) = QMainWindow::_aqt_metacall
{
_id ( ,,);_cif _id( _a<0
) return_id ; if(
== _id::
) if_c ( QMetaObject<InvokeMetaMethod3 {
) qt_static_metacall_id ( this,
,,); _c-= _id3 _a;}
_id else if(
== :: ) if_c ( QMetaObject<RegisterMethodArgumentMetaType3 {
) *_id reinterpret_cast <int
*([0]>)_a=-1; -= 3;}
_id return ;}
/****************************************************************************
** Meta object code from reading C++ file 'mycamera.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
# _idinclude
"mycamera.h"
QT_END_MOC_NAMESPACE
moc_mycamera.cpp
#
include# include
#if
!defined
() #error#Q_MOC_OUTPUT_REVISIONelif
!=67 "The header file 'mycamera.h' doesn't include ."
#error Q_MOC_OUTPUT_REVISION "This file was generated using the moc from 5.7.0. It" #
error"cannot be used with the include files from this version of Qt." #
error"(The moc has changed too much.)" #
endifstruct qt_meta_stringdata_mycamera_t
[1
QT_BEGIN_MOC_NAMESPACE
] ; {
QByteArrayData datachar[9]
; stringdata0};#define
QT_MOC_LITERAL(
,, )\idxQ_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET ofs( len, \
qptrdiff(lenoffsetof (
,)+\qt_meta_stringdata_mycamera_t- stringdata0* sizeof ofs (
) idx ) \)QByteArrayDatastaticconst =
QT_MOC_LITERAL
( 0 qt_meta_stringdata_mycamera_t qt_meta_stringdata_mycamera , {
{
0,8) // "mycamera"} ,"mycamera" }
;#
undef
QT_MOC_LITERALstatic
const[ ]
= // content: uint qt_meta_data_mycamera7, // revision {
0
,// classname 0
,0 ,
// classinfo0 ,0 ,
// methods0 ,0 ,
// properties0 ,0 ,
// enums/sets0 ,0 ,
// constructors0 ,// flags 0
,// signalCount 0
// eod} ;
void ::
qt_static_metacall(
* mycamera,::,QObject int_o, QMetaObjectvoidCall _c* * _id) Q_UNUSED ()_a;
{
Q_UNUSED(_o);
Q_UNUSED(_id);
Q_UNUSED(_c);
}const_a::=
&
:: QMetaObject mycamera,staticMetaObject . {
{ ,QMainWindow,staticMetaObject, qt_meta_stringdata_mycamera,data}
qt_meta_data_mycamera} qt_static_metacall; Q_NULLPTRconst Q_NULLPTR*
::metaObject
( QMetaObject )mycameraconstreturn::? ::
{
dynamicMetaObject QObject(d_ptr->metaObject ) QObject:d_ptr->&;} void *staticMetaObject::
qt_metacast
( constmycamerachar*)if ( !_clname)
{
return ;if_clname( ! Q_NULLPTRstrcmp
( ,.))_clnamereturn qt_meta_stringdata_mycamerastatic_caststringdata0<void
* (const_cast<*>(this) mycamera)>;returnQMainWindow::qt_metacast
( );}int_clname::qt_metacall
(
:: mycamera,int,QMetaObjectvoidCall _c* * _id) = QMainWindow::_aqt_metacall
{
_id ( ,,);_cif _id( _a<0
) return_id ; return;
} _id#
ifndef _idMYCAMERA_H
#
QT_END_MOC_NAMESPACE
mycamera.h
defineMYCAMERA_H #
include# include
#include
//V4L2对应的头文件#
include# include
#include
#include
#include
#include
#include
#include
#define
W640
#define H 480
//自定义结构体,用来存放每个缓冲块的首地址和大小struct bufmsg void
*
; //缓冲块的首地址
{
int ;start//缓冲块的大小 }
; somelenclass mycamera
:public
QMainWindow public : explicit mycamera
{
Q_OBJECT
(*
= nullptr)QWidget ;parent //摄像头的初始化 intcamera_init(
)
; //摄像头捕捉显示画面intcamera_capture(
)
; //关闭摄像头intcamera_uninit(
)
; :private:int
signals;
int*
; lcdfdint
; //分配缓冲块顺便映射得到4个缓冲块的首地址lcdmemstruct
v4l2_buffer camerafd;
//定义结构体数组存放4个缓冲块的首地址和大小
struct bufmsg otherbuf[
4
] ; arrayenumv4l2_buf_type;}
; # mytypeendif
// MYCAMERA_H#
include"mycamera.h" //封装函数--》把一组YUV--》转换ARGB数据
mycamera.cpp
intyuvtoargb (
int
, int,int y)int u,, v;
{
int r;g=b+
1.4075 pix*
r ( y - 128); v = -0.3455*
g ( y - 128)- u 0.7169 *( - 128); v = +1.779*
b ( y - 128); u //修正计算结果 0---255之间 if(255
)
=255r>;if
r(255)
=255g>;if
g(255)
=255b>;if
b(<0
)=r0;if
r(<0
)=g0;if
g(<0
)=b0;//把rgb拼接得到ARGB
b=0x00<<
24
pix|<<16|<<r8|;greturn;}b//封装函数--》把一帧画面数据中所有的YUYV数据转换成ARGB数据
//参数:yuv --》指向一帧yuyv画面首地址 pix// argbbuf --》存放转换得到的完整的ARGB数据
//allyuvtoargb(array[i].start,argbbuf)
/*
yuv[0]--第一个Y
yuv[1]-- U
yuv[2]--第二个Y
yuv[3]-- V
*/
int
allyuvtoargb
(
char
* ,int* )yuvint, ;argbbuffor
{
( i=j0
,=i0;<j*;+= i2W,H+= i4)//一组YUYV转换得到两组ARGB数据j[]=
{
yuvtoargb
argbbuf(i[],[yuv+j1]yuv,j[+3]yuv)j;[+1]
argbbuf=iyuvtoargb([+2]yuv,j[+1]yuv,j[+3]yuv)j;}return0;
}
:: mycamera(
*
mycamera):QMainWindowQWidget (parent) } //摄像头初始化intparent::
{
camera_init
(
) mycameraint;int;
{
//打开lcd ret=
open i(
"/dev/fb0"
lcdfd,);if(O_RDWR==-
1)lcdfdperror("打开lcd失败!\n")
{
;return-1;
} //映射得到lcd的首地址=(
int
*
lcdmem)mmap( NULL,800*480*4,|,,,PROT_READ0PROT_WRITE)MAP_SHARED;lcdfdif(==NULL
)perrorlcdmem("映射lcd失败了!\n")
{
;return-1;
} //打开摄像头的驱动=open
(
"/dev/video7"
camerafd,);if(O_RDWR==-
1)camerafdperror("打开摄像头失败!\n")
{
;return-1;
} //设置摄像头采集格式structv4l2_format
;
bzero
( & myfmt,
sizeof()myfmt);.myfmt=;.
myfmt.type.V4L2_BUF_TYPE_VIDEO_CAPTURE=
myfmt;fmt.pix.width.W=
myfmt;fmt.pix.height.H=
myfmt;fmt=pixioctlpixelformat(V4L2_PIX_FMT_YUYV,
ret,&)camerafd;VIDIOC_S_FMTif(myfmt==-
1)retperror("设置采集格式失败!\n")
{
;return-1;
} //申请4个缓冲块structv4l2_requestbuffers
;
bzero
( & mybuf,
sizeof()mybuf);.mybuf=4;
mybuf//4个缓冲块count.=; .
mybuf=type;V4L2_BUF_TYPE_VIDEO_CAPTURE=
mybufioctlmemory(V4L2_MEMORY_MMAP,
ret,&)camerafd;VIDIOC_REQBUFSif(mybuf==-
1)retperror("申请缓冲块失败!\n")
{
;return-1;
} for(=
0
;<i4;++ i)bzero( i&,
{
sizeof()otherbuf);.otherbuf=;//索引号
otherbuf.index=i; .
otherbuf=type;V4L2_BUF_TYPE_VIDEO_CAPTURE=
otherbufioctlmemory(V4L2_MEMORY_MMAP,
ret,&)camerafd;VIDIOC_QUERYBUFif(otherbuf==-
1)retperror("分配缓冲块失败!\n")
{
;return-1;
} //顺便映射得到4个缓冲块的首地址[]
.
=
array.i;[somelen]otherbuf.length=
arraymmapi(NULLstart,.,|,otherbuf,length,PROT_READ.PROT_WRITE.MAP_SHARED)camerafd;otherbufifm(offset[]
.==arrayNULLi)perrorstart("映射缓冲块失败了!\n")
{
;return-1;
} //顺便发送入队申请(一旦摄像头启动了,立马把画面入队)=ioctl
(
,
ret,&)camerafd;VIDIOC_QBUFif(otherbuf==-
1)retperror("入队失败!\n")
{
;return-1;
} }//启动摄像头捕捉=
;
=
ioctl
mytype(V4L2_BUF_TYPE_VIDEO_CAPTURE,
ret,&)camerafd;VIDIOC_STREAMONif(mytype==-
1)retperror("启动摄像头捕捉失败!\n")
{
;return-1;
} return0;
}
//摄像头捕捉画面,显示 int::
camera_capture
(
) mycameraint;int,
{
; ret//定义一个数组存放转换得到的一帧完整的ARGB数据
int i[j*
]
; argbbuf//定义集合存放要监测的文件描述符W;HFD_ZERO(
&
fd_set myset)
;FD_SET(myset,&
);camerafd//让摄像头画面循环出队,入队形成视频流在lcd上显示出来formyset(=
0
;<i4;++ i)//监测摄像头队列中是否有数据可读= iselect(
{
+
ret1,&camerafd,NULL,NULLmyset,NULL);if(0)
//说明摄像头的缓冲区中有画面入队了//出队ret>bzero( &
{
,
sizeof()otherbuf);.otherbuf=;//索引号
otherbuf.index=i; .
otherbuf=type;V4L2_BUF_TYPE_VIDEO_CAPTURE=
otherbufioctlmemory(V4L2_MEMORY_MMAP,
ret,&)camerafd;VIDIOC_DQBUFif(otherbuf==-
1)retperror("出队失败!\n")
{
;return-1;
} //出队画面(在结构体数组里面存放着)在lcd上显示出来//array[i].start --》 当前出队的画面数据(YUV格式)首地址//array[i].somelen --》当前出队的画面数据大小
//YUV格式无法直接在lcd上显示,原因是lcd只能显示ARGB数据
/*
第一行数据: argbbuf[0]--argbbuf[W-1]
lcdmem
第二行数据: argbbuf[W]--argbbuf[2*W-1]
lcdmem+下一行
*/
allyuvtoargb
(
(
char
*)([ ].)array,i);start//把argbbuf中的数据填充到lcd对应的位置forargbbuf(=
0
;<j;++) jmemcpyH( j+80
+800lcdmem*,&[*j],argbbuf*W4j);W//入队=ioctl(
,
ret,&)camerafd;VIDIOC_QBUFif(otherbuf==-
1)retperror("入队失败!\n")
{
;return-1;
} }}return
0
;
}
//摄像头关闭 int::
camera_uninit
(
) mycameraint;int;
{
//收尾 ret=
ioctl i(
,
ret,&)camerafd;VIDIOC_STREAMOFFif(mytype==-
1)retperror("关闭摄像头捕捉失败!\n")
{
;return-1;
} munmap(,
800
*480lcdmem*4);for(=0
;<i4;++ i)munmap( i[]
.,array[i].start)array;i::closesomelen()
;::closelcdfd()
;return0camerafd;}
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.7.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/ #ifndef
UI_MAINWINDOW_H
ui_mainwindow.h
#
defineUI_MAINWINDOW_H #
include# include
#include
#include
#include
#include
#include
#include
#include
#include
#include
classUi_MainWindow
public:
QT_BEGIN_NAMESPACE
* ;
{
*;
QWidget *centralwidget;
QPushButton *startbt;
QPushButton *closebt;
QLabel *label;
QMenuBar voidmenubarsetupUi
QStatusBar (statusbar*
) if(QMainWindow objectNameMainWindow(
{
) .MainWindow->isEmpty())setObjectName(QStringLiteral(
MainWindow->"MainWindow"));resize(800,
MainWindow->480);= newQWidget(
centralwidget ) ; setObjectName(MainWindowQStringLiteral(
centralwidget->"centralwidget"));=newQPushButton(
startbt ) ; setObjectName(centralwidgetQStringLiteral(
startbt->"startbt"));setGeometry(QRect(
startbt->0,0,80, 480) ); =newQPushButton(
closebt ) ; setObjectName(centralwidgetQStringLiteral(
closebt->"closebt"));setGeometry(QRect(
closebt->720,0,80, 480) ); =newQLabel(
label ) ; setObjectName(centralwidgetQStringLiteral(
label->"label"));setGeometry(QRect(
label->80,0,640, 480) ); setStyleSheet(QStringLiteral(
label->"background-color: rgb(255, 0, 0);"));setCentralWidget();
MainWindow->=newcentralwidgetQMenuBar(
menubar ) ; setObjectName(MainWindowQStringLiteral(
menubar->"menubar"));setGeometry(QRect(
menubar->0,0,800, 22) ); setMenuBar();
MainWindow->=newmenubarQStatusBar(
statusbar ) ; setObjectName(MainWindowQStringLiteral(
statusbar->"statusbar"));setStatusBar();
MainWindow->retranslateUi(statusbar);
QMetaObject::MainWindowconnectSlotsByName(
);}// setupUiMainWindowvoidretranslateUi
( *
) setWindowTitle(QMainWindow QApplicationMainWindow::
{
MainWindow->translate("MainWindow","MainWindow",0) ); setText(QApplication::
startbt->translate("MainWindow","507520",0) ); setText(QApplication::
closebt->translate("MainWindow","553175",0) ); setText(QString(
label->));}// retranslateUi};
namespace class
MainWindow:
public Ui {
Ui_MainWindow }; } // namespace Ui {#endif
// UI_MAINWINDOW_H #
QT_END_NAMESPACE
include"mainwindow.h" #
【4】用多线程实现V4L2摄像头显示
mian.c
includeint main
(int
, char*[ argc] ) aargv(,)
{
QApplication ;;argc. argvshow(
MainWindow w)
w;return.exec(
) a;}#ifndefMAINWINDOW_H
#
mainwindow.h
defineMAINWINDOW_H #
include# include
"mycamera.h"namespace
classMainWindow ;
QT_BEGIN_NAMESPACE
} Ui { class MainWindow: public
QT_END_NAMESPACE
QMainWindow public : MainWindow (
{
Q_OBJECT
*=
nullptr)QWidget ;parent ~ MainWindow()
;private:voidon_startbt_clicked
( slots)
; voidon_closebt_clicked()
; private:::*
;;
Ui//由于mycamera继承了QThreadMainWindow }ui;
mycamera cam# endif
// MAINWINDOW_H#
include"mainwindow.h" #
mainwindow.cpp
include"ui_mainwindow.h" MainWindow
::MainWindow (
*):QMainWindowQWidget (parent)
, ui(parentnew
:: )setupUi( UithisMainWindow)
{
ui->;//构造函数中初始化摄像头.camera_init(
)
cam;}MainWindow::~
MainWindow
()//在析构函数中关闭摄像头.camera_uninit(
{
)
cam;delete;}//启动摄像头(实际上是启动线程,在run方法中不断地捕捉画面)
void uiMainWindow
::
on_startbt_clicked
( ).start()
{
cam;//会自动帮助你执行run}//关闭摄像头(实际上是终止线程)void MainWindow
::
on_closebt_clicked
( ).terminate()
{
cam;}<?=
"1.0"
mainwindow.ui
="UTF-8"xml version?< encoding="4.0"<>
classui version</>
class<>MainWindowclass="QMainWindow">
=widget "MainWindow"<= name"geometry"<>
<property name0<>
/rect>
<x>0</x>
<y>800</y>
<width>480</width>
<height>/</height>
<=rect>
"windowTitle"<property>
<property name/<>
/string>MainWindow<classstring>
="QWidget"property>
=widget "centralwidget"<class name="QPushButton">
=widget "startbt"<= name"geometry"<>
<property name0<>
/rect>
<x>0</x>
<y>80</y>
<width>480</width>
<height>/</height>
<=rect>
"text"<property>
<property name/<>
/string>启动</string>
<classproperty>
="QPushButton"widget>
=widget "closebt"<= name"geometry"<>
<property name720<>
/rect>
<x>0</x>
<y>80</y>
<width>480</width>
<height>/</height>
<=rect>
"text"<property>
<property name/<>
/string>关闭</string>
<classproperty>
="QLabel"widget>
=widget "label"<= name"geometry"<>
<property name80<>
/rect>
<x>0</x>
<y>640</y>
<width>480</width>
<height>/</height>
<=rect>
"styleSheet"<property>
=property name"true"->
:string notrrgb(>background255color, 0,0) ;< /</<=string>
"text"<property>
/property name</>
<string/>
</property>
<classwidget>
="QMenuBar"widget>
=widget "menubar"<= name"geometry"<>
<property name0<>
/rect>
<x>0</x>
<y>800</y>
<width>22</width>
<height>/</height>
</rect>
<classproperty>
="QStatusBar"widget>
=widget "statusbar"/< name/</>
</widget>
<resources/>
/****************************************************************************
** Meta object code from reading C++ file 'mainwindow.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/connections#>
include"mainwindow.h"ui>
ui界面
#
include# include
#if
!defined
() #error#Q_MOC_OUTPUT_REVISIONelif
!=67 "The header file 'mainwindow.h' doesn't include ."
#error Q_MOC_OUTPUT_REVISION "This file was generated using the moc from 5.7.0. It" #
error"cannot be used with the include files from this version of Qt." #
error"(The moc has changed too much.)" #
endifstruct qt_meta_stringdata_MainWindow_t
[4
QT_BEGIN_MOC_NAMESPACE
] ; {
QByteArrayData datachar[50]
; stringdata0};#define
QT_MOC_LITERAL(
,, )\idxQ_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET ofs( len, \
qptrdiff(lenoffsetof (
,)+\qt_meta_stringdata_MainWindow_t- stringdata0* sizeof ofs (
) idx ) \)QByteArrayDatastaticconst =
QT_MOC_LITERAL
( 0 qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow , {
{
0,10) ,// "MainWindow" QT_MOC_LITERAL(1 ,
11,18) ,// "on_startbt_clicked" QT_MOC_LITERAL(2 ,
30,0) ,// "" QT_MOC_LITERAL(3 ,
31,18) // "on_closebt_clicked"} ,"MainWindow"on_closebt_clicked"on_startbt_clicked};" #
undefQT_MOC_LITERAL
static
const
[]
=// content: 7
, // revision uint qt_meta_data_MainWindow0, // classname {
0
,0 ,
// classinfo2 ,
14, // methods0 ,
0, // properties0 ,
0, // enums/sets0 ,
0, // constructors0 ,
// flags0 ,// signalCount // slots: name, argc, parameters, tag, flags
1, 0
,24 ,
2
,0x08 /* Private */, 3, 0, 25 ,2
,0x08 /* Private */, // slots: parameters:: ,:: , 0// eod
}
QMetaType;Voidvoid
QMetaTypeMainWindowVoid::
qt_static_metacall (
*,
:: ,int,voidQObject *_o* QMetaObject)Call _cif ( _id== :: )*_a=
{
static_cast <_c * QMetaObject(InvokeMetaMethod) {
MainWindow ;_t Q_UNUSED ()MainWindow switch>(_o)case
0:_ton_startbt_clicked
( )_id; {
break ;case _t->1:on_closebt_clicked( );
break ;default _t->:;}} Q_UNUSED(
); }
const
::
=&_a::,
.
, QMetaObject MainWindow,staticMetaObject , {
{ ,QMainWindow}staticMetaObject} qt_meta_stringdata_MainWindow;dataconst
qt_meta_data_MainWindow* qt_static_metacallMainWindow Q_NULLPTR:: Q_NULLPTRmetaObject
()
const QMetaObject return::?::dynamicMetaObject( )
{
: QObject&d_ptr->metaObject ; QObject}d_ptr->void*MainWindow :: qt_metacaststaticMetaObject(
const
char *)if(!) return ;_clnameif
{
( !strcmp_clname( , Q_NULLPTR.
) )returnstatic_cast<_clnamevoid qt_meta_stringdata_MainWindow*stringdata0(const_cast
< *(this)>);return MainWindowQMainWindow>::qt_metacast();
} intMainWindow::qt_metacall_clname(::
,
int ,void**QMetaObject)Call _c= QMainWindow _id:: qt_metacall (,_a,
{
_id ) ;if(<_c0 _id) _areturn;
if (_id == ::)
if _id(
< 2_c ) QMetaObjectqt_static_metacallInvokeMetaMethod( {
this ,_id , ,)
;-=2; _c} _idelse _aif(
_id == ::)
if ( < 2_c ) QMetaObject*RegisterMethodArgumentMetaTypereinterpret_cast {
< int_id * ([
0])=->1_a;-=2; } return;}
_id /****************************************************************************
** Meta object code from reading C++ file 'mycamera.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/ #include
"mycamera.h"
# _idinclude
#
QT_END_MOC_NAMESPACE
moc_mycamera.cpp
include
#if !
defined(
)#
error# elif!=67Q_MOC_OUTPUT_REVISION#
error"This file was generated using the moc from 5.7.0. It" "The header file 'mycamera.h' doesn't include ."
#error Q_MOC_OUTPUT_REVISION "cannot be used with the include files from this version of Qt." #
error"(The moc has changed too much.)" #
endifstruct qt_meta_stringdata_mycamera_t
[1 ]
;char
QT_BEGIN_MOC_NAMESPACE
[ 9 {
QByteArrayData data];};
# stringdata0defineQT_MOC_LITERAL(,
,)
\Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET (,idx\ ofsqptrdiff len( offsetof
(,len) +
\-*sizeofqt_meta_stringdata_mycamera_t( stringdata0) ) ofs \
) idx static const=QByteArrayDataQT_MOC_LITERAL( 0
,
0 , qt_meta_stringdata_mycamera_t qt_meta_stringdata_mycamera 8 {
{
)// "mycamera"}, "mycamera"} ;# undef
QT_MOC_LITERALstatic
const
[]
=// content: 7
, // revision uint qt_meta_data_mycamera0, // classname {
0
,0 ,
// classinfo0 ,
0, // methods0 ,
0, // properties0 ,
0, // enums/sets0 ,
0, // constructors0 ,
// flags0 ,// signalCount 0
// eod} ;
void:: qt_static_metacall
( *
,::
, mycameraint,voidQObject *_o* QMetaObject)Call _cQ_UNUSED ( _id) ; Q_UNUSED(_a)
{
;Q_UNUSED_o()
;Q_UNUSED_id()
;}_cconst::
=&_a::,
.
, QMetaObject mycamera,staticMetaObject , {
{ ,QThread}staticMetaObject} qt_meta_stringdata_mycamera;dataconst
qt_meta_data_mycamera* qt_static_metacall:: Q_NULLPTRmetaObject Q_NULLPTR(
)const
return QMetaObject ::mycamera?::dynamicMetaObject( )
{
: QObject&d_ptr->metaObject ; QObject}d_ptr->void*:: qt_metacast (staticMetaObjectconst
char
* )mycameraif(!) return ;_clnameif
{
( !strcmp_clname( , Q_NULLPTR.
) )returnstatic_cast<_clnamevoid qt_meta_stringdata_mycamera*stringdata0(const_cast
< *(this)>);return mycameraQThread>::qt_metacast();
} int::qt_metacall(_clname::,
int
, mycameravoid**QMetaObject)Call _c= QThread _id:: qt_metacall (,_a,
{
_id ) ;if(<_c0 _id) _areturn;
return ;_id } #ifndef
MYCAMERA_H _id#
define _idMYCAMERA_H
#
QT_END_MOC_NAMESPACE
mycamera.h
include# include
#include //V4L2对应的头文件
#include
#include
#include #
include#
include#
include#
include#
include#
defineW
640#
defineH
480//自定义结构体,用来存放每个缓冲块的首地址和大小 struct bufmsg
void* ; //缓冲块的首地址
int
; //缓冲块的大小
{
} ;startclass mycamera
: somelenpublic QThread
public:
explicit mycamera ( ) ;
{
Q_OBJECT
//重写父类的同名虚函数runvoid
run ();//摄像头的初始化
int
camera_init (); //摄像头捕捉显示画面
int
camera_capture ();//关闭摄像头
int
camera_uninit ();:
private
: int;int*
signals;
int;
//分配缓冲块顺便映射得到4个缓冲块的首地址 lcdfdstruct
v4l2_buffer ;lcdmem//定义结构体数组存放4个缓冲块的首地址和大小
struct camerafdbufmsg
[
4 ] otherbuf;
enum
v4l2_buf_type ; array};#endif
// MYCAMERA_H # mytypeinclude
"mycamera.h"//封装函数--》把一组YUV--》转换ARGB数据
intyuvtoargb (
mycamera.cpp
int, int
,
int )int, y,; uint; v=
{
+ r1.4075g*b(
- pix128
r ) y ; =-0.3455 v * (-128
g ) y - 0.7169*( u - 128) ; =+1.779 v * (-128
b ) y ; //修正计算结果 0---255之间if( u 255 )=255
;
if(r>255)
r=255;
if(g>255)
g=255;
if(b><0
b)=0
;ifr(<0
r)=0
;ifg(<0
g)=0
;//把rgb拼接得到ARGBb=0x00<<
b24|<<
16
pix|<<8|;rreturn;}g//封装函数--》把一帧画面数据中所有的YUYV数据转换成ARGB数据//参数:yuv --》指向一帧yuyv画面首地址// argbbuf --》存放转换得到的完整的ARGB数据b//allyuvtoargb(array[i].start,argbbuf)
/*
yuv[0]--第一个Y
yuv[1]-- U
yuv[2]--第二个Y
yuv[3]-- V
*/ pixint
allyuvtoargb
(
char
*
,
int
* )int, ;yuvfor( =argbbuf0
{
, i=j0
;<i*;+=j2,+= i4W)H//一组YUYV转换得到两组ARGB数据 i[]=jyuvtoargb([
{
]
argbbuf,i[+1]yuv,j[+yuv3j]);[yuv+j1]=yuvtoargb(
argbbuf[i+2],[+yuv1j],[+yuv3j]);}yuvreturnj0;}::mycamera
(
) :QThread
(
mycamera)}void:: run ()//循环显示摄像头拍摄的画面
{
while
( mycamera1)camera_capture(
{
)
;}}//摄像头初始化
{
int::camera_init(
)
int
;
int mycamera;//打开lcd=open
{
( ret"/dev/fb0"
, i)
;
lcdfdif(==-1O_RDWR)perror
("打开lcd失败!\n"lcdfd);return-
{
1;}//映射得到lcd的首地址=
( int*)
mmap
(
lcdmemNULL,800 *480*4,|,,,0);PROT_READifPROT_WRITE(MAP_SHARED==lcdfdNULL)perror(
"映射lcd失败了!\n")lcdmem;return-
{
1;}//打开摄像头的驱动=
open ("/dev/video7",
)
;
camerafdif(==-1O_RDWR)perror
("打开摄像头失败!\n"camerafd);return-
{
1;}//设置摄像头采集格式struct
v4l2_format ;bzero(
&
,
sizeof ( myfmt)
);.myfmt=;.myfmt..=
myfmt;type.V4L2_BUF_TYPE_VIDEO_CAPTURE.
myfmt.fmt=pix;width.W.
myfmt.fmt=pix;height=Hioctl
myfmt(fmt,pix,pixelformat&V4L2_PIX_FMT_YUYV)
ret;if(camerafd==VIDIOC_S_FMT-1myfmt)perror
("设置采集格式失败!\n"ret);return-
{
1;}//申请4个缓冲块struct
v4l2_requestbuffers ;bzero(
&
,
sizeof ( mybuf)
);.mybuf=4;mybuf//4个缓冲块.=
mybuf;count.=; =
mybufioctltype(V4L2_BUF_TYPE_VIDEO_CAPTURE,
mybuf,memory&V4L2_MEMORY_MMAP)
ret;if(camerafd==VIDIOC_REQBUFS-1mybuf)perror
("申请缓冲块失败!\n"ret);return-
{
1;}for(
= 0;<
4
;++i)bzero( i&,sizeof i()
{
);.otherbuf=;//索引号otherbuf.=;
otherbuf.index=i; =
otherbufioctltype(V4L2_BUF_TYPE_VIDEO_CAPTURE,
otherbuf,memory&V4L2_MEMORY_MMAP)
ret;if(camerafd==VIDIOC_QUERYBUF-1otherbuf)perror
("分配缓冲块失败!\n"ret);return-
{
1;}//顺便映射得到4个缓冲块的首地址[
] .=.
;
[
array]i.=somelenmmapotherbuf(lengthNULL
array,i.,start|,,,.otherbuf.length)PROT_READ;PROT_WRITEifMAP_SHARED(camerafd[otherbuf]m.offset==NULL
)perrorarray(i"映射缓冲块失败了!\n")start;return-
{
1;}//顺便发送入队申请(一旦摄像头启动了,立马把画面入队)=
ioctl (,,
&
)
ret;if(camerafd==VIDIOC_QBUF-1otherbuf)perror
("入队失败!\n"ret);return-
{
1;}}//启动摄像头捕捉
= ;=ioctl
(
,
,
mytype&V4L2_BUF_TYPE_VIDEO_CAPTURE)
ret;if(camerafd==VIDIOC_STREAMON-1mytype)perror
("启动摄像头捕捉失败!\n"ret);return-
{
1;}return0
; }//摄像头捕捉画面,显示int
::
camera_capture ()
int
;
int mycamera,;//定义一个数组存放转换得到的一帧完整的ARGB数据int
{
[ ret*
] i;j//定义集合存放要监测的文件描述符
;
FD_ZERO argbbuf(W&H);
FD_SET
fd_set myset(
,&)myset;//让摄像头画面循环出队,入队形成视频流在lcd上显示出来
for(camerafd=0myset;<
4
;++i)//监测摄像头队列中是否有数据可读= iselect(+ i1,
{
&
ret,NULL,camerafdNULL,NULL)myset;if(0)//说明摄像头的缓冲区中有画面入队了//出队bzero
(&ret>,sizeof (
{
)
);.otherbuf=;//索引号otherbuf.=;
otherbuf.index=i; =
otherbufioctltype(V4L2_BUF_TYPE_VIDEO_CAPTURE,
otherbuf,memory&V4L2_MEMORY_MMAP)
ret;if(camerafd==VIDIOC_DQBUF-1otherbuf)perror
("出队失败!\n"ret);return-
{
1;}//出队画面(在结构体数组里面存放着)在lcd上显示出来//array[i].start --》 当前出队的画面数据(YUV格式)首地址
//array[i].somelen --》当前出队的画面数据大小 //YUV格式无法直接在lcd上显示,原因是lcd只能显示ARGB数据/*
第一行数据: argbbuf[0]--argbbuf[W-1]
lcdmem
第二行数据: argbbuf[W]--argbbuf[2*W-1]
lcdmem+下一行
*/allyuvtoargb
(
(
char
*
)
(
[].) ,);array//把argbbuf中的数据填充到lcd对应的位置ifor(start=0argbbuf;<
;
++)jmemcpy(+ j80H+ j800*
,&lcdmem[*],*j4)argbbuf;W//入队j=ioctlW(,,&
)
ret;if(camerafd==VIDIOC_QBUF-1otherbuf)perror
("入队失败!\n"ret);return-
{
1;}}}
return 0;}
//摄像头关闭
int
::
camera_uninit ()
int
;
int mycamera;//收尾=ioctl
{
( ret,
, i&
)
ret;if(camerafd==VIDIOC_STREAMOFF-1mytype)perror
("关闭摄像头捕捉失败!\n"ret);return-
{
1;}munmap(
, 800*480
*
4)lcdmem;for(=0;<4
;++i)munmap( i[]. i,[
].array)i;::startclosearray(i);somelen::close
();lcdfdreturn0
;}/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.7.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/camerafd#ifndef
UI_MAINWINDOW_H #define
UI_MAINWINDOW_H
ui_mainwindow.h
#
include# include
#include #
include#
include#
include#
include#
include#
include#
include#
includeclass
Ui_MainWindowpublic
:*
;*
QT_BEGIN_NAMESPACE
; *
{
;*
QWidget ;centralwidget*
QPushButton ;startbt*
QPushButton ;closebtvoid
QLabel setupUilabel(
QMenuBar *menubar)
QStatusBar ifstatusbar(
objectName ()QMainWindow .MainWindowisEmpty
{
( )MainWindow->)setObjectName(QStringLiteral("MainWindow"))
MainWindow->;resize(800,480);
MainWindow->=newQWidget( );setObjectName
centralwidget ( QStringLiteral ("centralwidget"MainWindow))
centralwidget->;=newQPushButton();setObjectName
startbt ( QStringLiteral ("startbt"centralwidget))
startbt->;setGeometry(QRect(0,0
startbt->,80,480)) ;= newQPushButton ();setObjectName
closebt ( QStringLiteral ("closebt"centralwidget))
closebt->;setGeometry(QRect(720,0
closebt->,80,480)) ;= newQLabel ();setObjectName
label ( QStringLiteral ("label"centralwidget))
label->;setGeometry(QRect(80,0
label->,640,480)) ;setStyleSheet (QStringLiteral ("background-color: rgb(255, 0, 0);"))
label->;setCentralWidget();=newQMenuBar
MainWindow->()centralwidget;setObjectName
menubar ( QStringLiteral ("menubar"MainWindow))
menubar->;setGeometry(QRect(0,0
menubar->,800,22)) ;setMenuBar () ;=newQStatusBar
MainWindow->()menubar;setObjectName
statusbar ( QStringLiteral ("statusbar"MainWindow))
statusbar->;setStatusBar();retranslateUi()
MainWindow->;QMetaObjectstatusbar::connectSlotsByName
()MainWindow;}
// setupUivoidretranslateUi(MainWindow*)
setWindowTitle (
QApplication ::translateQMainWindow (MainWindow"MainWindow"
{
MainWindow->,"MainWindow",0));setText (QApplication ::translate("MainWindow"
startbt->,"507520",0));setText (QApplication ::translate("MainWindow"
closebt->,"553175",0));setText (QString ());
label->}// retranslateUi};namespaceclassMainWindow
: public
Ui_MainWindow}
; Ui {
} // namespace Ui# endif // UI_MAINWINDOW_H {
QT_END_NAMESPACE
源码项目文件,自取
第一期 QT上位机安装与新建项目教程
第二期 QT平台使用规则和代码逻辑学习
第三期 QT中信号与槽和字符串QString的使用
第四期 QT组件布局管理器和多界面传参跳转
第五期 QT消息盒子-对话框-定时器-日期和时间
第六期 QTmplayer视频播放器+列表框+交叉编译QT程序+QT控制硬件+多进程
第七期 QTwindows打包QT工程+多线程QThread+菜单栏+打包QT程序
第八期 QT网络编程TCP/IP/UDP+Http和JSON解析+qt事件软键盘
第九期 QT音视频Linux中的V4L2摄像头编程
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)