xcamera_record.h
#pragma once
#include <string>
#include "xtools.h"
class XCameraRecord :public XThread
{
public:
void set_rtsp_url(std::string url) { rtsp_url_ = url; }
void set_save_path(std::string s) { save_path_ = s; }
void set_file_sec(int s) { file_sec_ = s; }//125
private:
void Main();
std::string rtsp_url_;
std::string save_path_;//存储的根目录125
long long file_sec_ = 5;//多少秒创建一个新文件125
};
xcamera_record.cpp
#include "xcamera_record.h"
#include "xdemux_task.h"
#include "xmux_task.h"
#include <chrono>
#include <iomanip>
#include <sstream>
using namespace std;
using namespace chrono;
/// 生成存储的视频文件名
static std::string GetFileName(string path)
{
stringstream ss;
//获取当前时间
auto t = system_clock::to_time_t(system_clock::now());
auto time_str = put_time(localtime(&t), "%Y_%m_%d_%H_%M_%S");
ss << path << "/" << "cam_" << time_str << ".mp4";
return ss.str();
}
void XCameraRecord::Main()//124
{
XDemuxTask demux;
XMuxTask mux;
if (rtsp_url_.empty())
{
LOGERROR("open rtsp url failed!");
return;
}
//自定重连
while (!is_exit_)
{
if (demux.Open(rtsp_url_)) //最坏情况阻塞1秒
{
break;
}
MSleep(10);
continue;
}
//音视频参数
auto vpara = demux.CopyVideoPara();
if (!vpara)
{
LOGERROR("demux.CopyVideoPara failed!");
//需要考虑demux 资源释放的问题
demux.Stop();
return;
}
//启动解封装线程,提前启动,防止超时
demux.Start();
auto apara = demux.CopyAudioPara();
AVCodecParameters* para = nullptr; //音频参数
AVRational* timebase = nullptr; //音频时间基数
if (apara)
{
para = apara->para;
timebase = apara->time_base;
}
//打开了封装
if (!mux.Open(GetFileName(save_path_).c_str(),
vpara->para, vpara->time_base,//视频参数
para, timebase)) //音频参数
{
LOGERROR("mux.Open rtsp_url_ failed!");
demux.Stop();
mux.Stop();
return;
}
demux.set_next(&mux);
mux.Start();
//当前时间
auto cur = NowMs();
while (!is_exit_)
{
//定时创建新的文件
if (NowMs() - cur > file_sec_ * 1000)
{
cur = NowMs();
mux.Stop(); //停止存储,写入索引
//打开了封装
if (!mux.Open(GetFileName(save_path_).c_str(),
vpara->para, vpara->time_base,//视频参数
para, timebase)) //音频参数
{
LOGERROR("mux.Open rtsp_url_ failed!");
demux.Stop();
mux.Stop();
return;
}
mux.Start();
}
MSleep(5);
}
mux.Stop();
demux.Stop();
}
main.cpp
int main(int argc, char* argv[])
{
const char* save_path = "./video/0/";
QDir dir;
dir.mkpath(save_path);
XCameraRecord xr;
xr.set_rtsp_url(
"v1080.mp4");
xr.set_save_path(save_path);
xr.Start();
QApplication a(argc, argv);
XViewer w;
w.show();
auto re = a.exec();
xr.Stop();
return re;
}
xmux_task.cpp
void XMuxTask::Main()
{
xmux_.WriteHead();
//找到关键帧
while (!is_exit_)
{
unique_lock<mutex> lock(mux_);
auto pkt = pkts_.Pop();
if (!pkt)
{
MSleep(1);
continue;
}
if (pkt->stream_index == xmux_.video_index()
&& pkt->flags & AV_PKT_FLAG_KEY) //关键帧
{
xmux_.Write(pkt);
av_packet_free(&pkt);
break;
}
//丢掉非视频关键帧
av_packet_free(&pkt);
}
while (!is_exit_)
{
unique_lock<mutex> lock(mux_);
auto pkt = pkts_.Pop();
if (!pkt)
{
MSleep(1);
continue;
}
xmux_.Write(pkt);
cout << "W" << flush;
av_packet_free(&pkt);
}
xmux_.WriteEnd();
xmux_.set_c(nullptr);
}
运行结果: