一、摄像头在哪里
chenling@chenling-virtual-machine:~$ cd /dev
chenling@chenling-virtual-machine:/dev$ ls video0
video0
/dev/video0
是摄像头位置,这里先加个权限:
sudo chmod 777 video0
二、连接摄像头
然后加个头文件:
extern "C"
{
#include <libavdevice/avdevice.h>
}
修改之前第三篇博文里视频编码的函数中内容:
//加在最开头
avdevice_register_all();
//定义输入封装格式为video4linux2,这是linux下特定的
AVInputFormat *IfmatC=av_find_input_format("video4linux2");
//avformat_open_input修改为:
avformat_open_input(&fmatC,"/dev/video0",IfmatC,NULL);//把IfmatC当作输入封装格式
运行发现报错找不到设备,这里要点击【虚拟机】->【设置】,然后:
![](https://cdn.jsdelivr.net/gh/wukurua/cloudimg@master/img/QQ图片20200614143936.png)
![](https://cdn.jsdelivr.net/gh/wukurua/cloudimg@master/img/QQ图片20200614144426.png)
就连上辽!快乐得八达鸟!
三、采集摄像头数据并转码成MP4文件
整体与第三篇博文视频编码几乎一致,除了循环的结束条件不一样,因为之前是把YUV转成MP4,视频里的帧读取完就结束了,但是摄像头一直录着啊!这该咋办?
我们可以在视频解码类里定义一个变量用来记录此时是否要继续录制视频:
bool isRecording;
然后定义并实现一个简单的槽函数:
public slots:
void changeIsRecording();
void FDecode::changeIsRecording()
{
if(isRecording==true)
isRecording=false;
else
isRecording=true;
}
在界面中定义一个槽函数和按钮并建立连接,这样一点击这个按钮就可以开始录制,再点击这个按钮就停止录制
class WelcomeWindow : public Widget
{
Q_OBJECT
public:
......
private:
......
QPushButton *btnYUV;
public slots:
......
void toYUV();
void toPic();
};
槽函数实现:
void WelcomeWindow::toYUV()
{
if(etFilePath->text().isEmpty())
lblTip->setText("Video Path is Empty!");
else
{
lblTip->setText("Generating......");
QString sql="SELECT videoStoragePath FROM t_setting;";
int col,row;
char **pResult;
SingleDBOption::getTable(sql,pResult,row,col);
fdecode->fileName=etFilePath->text();
fdecode->dstDir=pResult[col];
fdecode->choose=CAMERA;
this->btnYUV->setText("停止录制视频");
fdecode->start();
}
}
连接:
connect(btnYUV,SIGNAL(clicked()),this,SLOT(toYUV()));
connect(btnYUV,SIGNAL(clicked()),fdecode,SLOT(changeIsRecording()));
视频解码类中把摄像头数据编码为YUV文件:
this->isRecording=true;//初始化为true,意为要录制视频
while(av_read_frame(fmatC,acPkt)==0)
{
QMutexLocker lock(&m_lock);
if(acPkt->stream_index==videoIndex)
{
if(this->isRecording==false)//如果停止录制,就break
break;
avcodec_decode_video2(codecContext,picture,&got_picture_ptr,acPkt);
if(got_picture_ptr)
{
sws_scale(sws_context,picture->data,picture->linesize,0,picture->height,dstFrame->data,dstFrame->linesize);
//encode
fev->encodeFrame(dstFrame);
}
}
av_packet_unref(acPkt);
}
转成mp4文件的代码与第四篇博文的转码成MP4的完全相同。