前言

参考了一些文章如下:

V4L2相关:点击跳转

其它文章:

Qt—Linux平台Qt5用V4L2读取摄像头,实现实时画面和拍照

V4L2+Qt5实现摄像头视频采集以及参数控制(源码学习版)_虾米小小小的博客-CSDN博客

一、项目功能简介

  • 监控画面显示及暂停

  • 画面录制

  • 录制视频回放

  • 录制文件以时间段为名保存

二、界面展示

界面展示

三、项目实现

1、整体流程

image-20211203162412813

2、功能实现

这里只展示了部分代码,完整代码请到最下方的链接下载

标志信息

1
2
3
4
5
6
7
bool stop_flag;             //用于标志是否暂停
bool record_flag; //用于标志是否正在录制
bool replay_flag; //用于标志是否正在回放
FILE *fp,*fp_replay; //文件指针,分别指向当前正在录制的视频文件和当前正在回放的视频文件
unsigned char pic[153600]; //用于保存从文件中读取的信息
unsigned char *display; //中间变量
int count; //用于分频

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
replay_pp = (unsigned char *)malloc(320 * 240/*QWidget::width()*QWidget::height()*/* 3 * sizeof(char));
v = (unsigned char *)malloc(153600);
replay_frame = new QImage(pp,320,240,QImage::Format_RGB888);

pp = (unsigned char *)malloc(320 * 240/*QWidget::width()*QWidget::height()*/* 3 * sizeof(char));
painter = new QPainter(this);
frame = new QImage(pp,320,240,QImage::Format_RGB888);
stop_flag = false;
record_flag = false;
replay_flag = false;
fp = NULL;
label = new QLabel();
btn_stop = new QPushButton(this);
btn_replay = new QPushButton(this);
btn_record = new QPushButton(this);
vd = new VideoDevice(tr("/dev/video0"));
count = 0;

connect(vd, SIGNAL(display_error(QString)), this,SLOT(display_error(QString)));
rs = vd->open_device();

停止功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void ProcessImage::on_btn_stop_clicked()
{
qDebug()<<"on_btn_stop_clicked";
if(!stop_flag)
{
stop_flag = true;
btn_stop->setText("Display");
}
else
{
stop_flag = false;
btn_stop->setText("Stop");
}
}

录制功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void ProcessImage::on_btn_record_clicked()
{
qDebug()<<"on_btn_record_clicked";
gettimeofday(&tv,NULL);//获取1970-1-1到现在的时间结果保存到tv中
sec=tv.tv_sec;
min=tv.tv_sec/60;
localtime_r((time_t*)&sec,&cur_tm);
snprintf(cur_time,20,"%d.%02d.%02d %02d:%02d:%02d",cur_tm.tm_year+1900,cur_tm.tm_mon+1,cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min,cur_tm.tm_sec);

if(!record_flag)
{
fp = fopen("/record_buf.yuv","wb+");
if(fp != NULL){qDebug()<<"fp open success";}
else{qDebug()<<"fp open fail";}
str1 = QString::fromLocal8Bit(cur_time);
qDebug()<<str1;
record_flag = true;
btn_record->setText("Stop_record");
}
else
{
if(fp != NULL)
{
fclose(fp);
qDebug()<<"fp closed";
}
str2= QString::fromLocal8Bit(cur_time);
qDebug()<<str2;
name = "/"+str1 + "-"+ str2;
qDebug()<<name;
rename("/record_buf.yuv",name.toLocal8Bit());
record_flag = false;
btn_record->setText("Record");
}
}

回放功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void ProcessImage::on_btn_replay_clicked()
{
qDebug()<<"on_btn_replay_clicked";
if(!replay_flag)
{
fp_replay = fopen(name.toLocal8Bit(),"rb+");
if(fp_replay != NULL){qDebug()<<"fp_replay open success";}
else{qDebug()<<"fp_replay open fail";}
replay_flag = true;
btn_replay->setText("Over_replay");
}
else
{
if(fp_replay != NULL)
{
fclose(fp_replay);
qDebug()<<"fp_replay open fail";
}
btn_replay->setText("Replay");
replay_flag = false;
}
}

图像获取与刷新

这里值得一提的是,下方代码的分频系数(5)可以用一个变量来替换,再加上一个按钮来控制这个变量的值,这样就可以实现回放视频的加速减速了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void ProcessImage::paintEvent(QPaintEvent *)
{
if(!stop_flag)
{
if(replay_flag)
{
count ++;
if(count == 5) //分频
{
if(fread(pic,1,153600,fp_replay)>=153600)
{
display = pic;
}
else
{
qDebug()<<"Read over";
rewind(fp_replay);
}
count = 0;
}
}
else
{
rs = vd->get_frame((void **)&p,(size_t *)&len);
if(record_flag)
{
qDebug()<<"Recording";
fwrite(p,153600,1,fp);
}
qDebug()<<"Displaying";
display = (unsigned char *)p;

}

if(!replay_flag || count == 0)
{
convert_yuv_to_rgb_buffer(display,pp,320,240/*QWidget::width(),QWidget::height()*/);
frame->loadFromData((uchar *)pp,/*len*/320 * 240 * 3 * sizeof(char));
label->setPixmap(QPixmap::fromImage(*frame,Qt::AutoColor));
}

if(!replay_flag)
{
rs = vd->unget_frame();
}
}
}

需要注意的一点是该程序在虚拟机上运行存在一点问题,无法正常运行,但在开发板上可以正常运行。有问题可以在评论区留言,最后在这里留下源代码下载地址

链接:https://pan.baidu.com/s/1_E1sUcUqxjIg5E-kyeMbVg
提取码:v4l2