多路h265监控录放开发-(11)定时录制视频并从关键帧开始录制

16 篇文章 0 订阅

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);
}

 运行结果:

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值