video analysis2.0拆分,ffmpeg封装go接口库
zhangmeng
2019-10-22 7fe46306ac577db11ba8a8bbf20653861fcb1a1a
csrc/worker/rec.cpp
@@ -16,11 +16,13 @@
using namespace ffwrapper;
using namespace cffmpeg_wrap::buz;
static const int cache_time = 30 * 60;
namespace cffmpeg_wrap
{
    rec::rec()
    :recRef_(NULL)
    ,min_cache_len_(10 * 60 * 25) // 最小缓存?分钟的视频,因为整个流程会有延迟,暂定?分钟
    ,min_cache_len_(cache_time * 25) // 最小缓存?分钟的视频,因为整个流程会有延迟,暂定?分钟
    {}
    rec::~rec()
@@ -43,6 +45,48 @@
        list_recInfo_.emplace_back(info);
    }
    void rec::findRecFramesIndex(const int64_t &fired_id, const int duration, int &start, int &end){
        start = end = -1;
        if (list_pkt_.empty()){
            return;
        }
        // 录像开始id在触发id之前1/2时长,保证在中间
        int64_t start_id = fired_id - duration/2;
        // 寻找关键帧作为录像开始id
        int offset = recRef_ ? recRef_->getFPS() : 25;
        int64_t index = -1;
        for(auto &i : list_pkt_){
            index++;
            // 跳过音频
            if(!recRef_->isVideoPkt(&i.data->getAVPacket())){
                continue;
            }
            // 寻找关键帧作为起始
            if (start < 0){
                if (i.data->getAVPacket().flags & AV_PKT_FLAG_KEY){
                    // 当前帧id > 开始id或开始id在offset内,作为起始录像帧
                    if (i.v_id >= start_id || start_id - i.v_id < offset){
                        start = index;
                        start_id = i.v_id;
                    }
                }
            }else if (recRef_->isVideoPkt(&i.data->getAVPacket())){
                // 视频帧,看是否缓存中有所有的duration数据
                if (i.v_id - start_id == duration){
                    end = index;
                }
            }
        }
        if (end < 0) end = index;
    }
    std::unique_ptr<buz::Recorder> rec::startRec(std::string id, std::string dir, const int64_t &frameID, const int mind, const int maxd, const bool audio){
        if(!recRef_){
            logIt("Init wrapper first");
@@ -63,8 +107,15 @@
        }
        
        if (trycnt < 100){
            int duration = mind * recRef_->getFPS();
            int start=0, end=0;
            std::lock_guard<std::mutex> locker(mtx_pkt_);
            rec->PushPackets(list_pkt_);
            logIt("cache size: %ld", list_pkt_.size());
            // 首次获取录像信息,先存一个最短时长
            findRecFramesIndex(frameID, duration, start, end);
            rec->StartWritePacket(list_pkt_, frameID, start, end);
            return rec;
        }
@@ -126,6 +177,9 @@
    void rec::Load(ffwrapper::FormatIn *in){
        recRef_ = in;
        if (in){
            min_cache_len_ = in->getFPS() * cache_time;
        }
    }
    void rec::Unload(){
@@ -165,30 +219,35 @@
        // logIt("recorders count: %d", map_rec_.size());
    }
    void rec::SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){
        if (!data) return;
    void rec::SetPacket(const CPacket &pkt){
        if (!pkt.data) return;
        cachePacket(pkt);
        std::lock_guard<std::mutex> l(mtx_rec_);
        for(auto &i : map_rec_){
            if (i.second){
                i.second->PushPacket({data, id});
                std::lock_guard<std::mutex> pl(mtx_pkt_);
                i.second->PushPacket(list_pkt_);
            }
        }
        cachePacket(data, id);
    }
    void rec::cachePacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){
    void rec::cachePacket(const CPacket &pkt){
        std::lock_guard<std::mutex> l(mtx_pkt_);
        //wait I 
        if (list_pkt_.empty()) {
            if (!recRef_->isVideoPkt(&pkt.data->getAVPacket())){
                return;
            }
            if (!(data->getAVPacket().flags & AV_PKT_FLAG_KEY)){
            if (!(pkt.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){
                return;
            }
        }
        
        list_pkt_.push_back({data, id});
        list_pkt_.push_back(pkt);
        // 超过缓存最大长度,删除一个gop
        shrinkCache();
@@ -204,20 +263,17 @@
    }
    int rec::shrinkCache(){
        //超过最大缓存,丢弃gop
        //缓存最小长度的,用于记录
        int fps = 25;
        if (recRef_){
            fps = recRef_->getFPS();
        }
        // 最小5秒长度
        int mincache = fps * 5;
        int md = min_cache_len_ < mincache ? mincache : min_cache_len_;
        while (list_pkt_.size() > md) {
        //超过最大缓存,丢弃gop
        while (list_pkt_.size() > min_cache_len_) {
            list_pkt_.pop_front();
            while(!list_pkt_.empty()){
                auto &i = list_pkt_.front();
                if (!(i.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){
                // 音频丢弃
                if (!recRef_->isVideoPkt(&i.data->getAVPacket())){
                    list_pkt_.pop_front();
                }else if (!(i.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){
                    // 非关键帧丢弃
                    list_pkt_.pop_front();
                }else{
                    break;