| | |
| | | #include <unistd.h> |
| | | #include <sys/time.h> |
| | | |
| | | extern "C"{ |
| | | #include <libavcodec/avcodec.h> |
| | | } |
| | | |
| | | #include "../ffmpeg/format/FormatIn.hpp" |
| | | #include "../ffmpeg/data/CodedData.hpp" |
| | | #include "../ffmpeg/log/log.hpp" |
| | |
| | | { |
| | | rec::rec() |
| | | :recRef_(NULL) |
| | | ,minduration_(250) |
| | | ,maxduration_(750) |
| | | ,min_cache_len_(10 * 60 * 25) // 最小缓存?分钟的视频,因为整个流程会有延迟,暂定?分钟 |
| | | {} |
| | | |
| | | rec::~rec() |
| | |
| | | list_recInfo_.emplace_back(info); |
| | | } |
| | | |
| | | std::unique_ptr<buz::Recorder> rec::startRec(std::string id, std::string dir, const int mind, const int maxd, const bool audio){ |
| | | 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"); |
| | | return nullptr; |
| | |
| | | if(ret == 0) break; |
| | | usleep(200000); |
| | | } |
| | | |
| | | if (trycnt < 100){ |
| | | std::lock_guard<std::mutex> locker(mtx_pkt_); |
| | | rec->PushPackets(list_pkt_); |
| | |
| | | return recRef_ != NULL; |
| | | } |
| | | |
| | | void rec::NewRec(const char* id, const char *output, const int mindur, const int maxdur, const bool audio){ |
| | | void rec::NewRec(const char* id, const char *output, const int64_t &frameID, const int mindur, const int maxdur, const bool audio){ |
| | | std::string rid(id); |
| | | std::string dir(output); |
| | | |
| | | minduration_ = mindur * 25; |
| | | maxduration_ = maxdur * 25; |
| | | |
| | | { |
| | | std::lock_guard<std::mutex> l(mtx_rec_); |
| | | if (map_rec_.find(rid) != map_rec_.end()){ |
| | | map_rec_.erase(rid); |
| | | } |
| | | map_rec_[rid] = startRec(rid, dir, mindur, maxdur, audio); |
| | | map_rec_[rid] = startRec(rid, dir, frameID, mindur, maxdur, audio); |
| | | } |
| | | |
| | | } |
| | |
| | | std::lock_guard<std::mutex> l(mtx_pkt_); |
| | | //wait I |
| | | if (list_pkt_.empty()) { |
| | | AVPacket &avpkt = data->getAVPacket(); |
| | | if (!(avpkt.flags & AV_PKT_FLAG_KEY)){ |
| | | |
| | | if (!(data->getAVPacket().flags & AV_PKT_FLAG_KEY)){ |
| | | return; |
| | | } |
| | | } |
| | | |
| | | list_pkt_.push_back({data, id}); |
| | | |
| | | // 超过缓存最大长度,删除一个gop |
| | | shrinkCache(); |
| | | } |
| | | |
| | | void rec::SetRecMinCacheTime(const int min){ |
| | | // 由于整个流程耗时,补偿time_offset_ |
| | | int fps = 25; |
| | | if (recRef_){ |
| | | fps = recRef_->getFPS(); |
| | | } |
| | | min_cache_len_ += min * fps; |
| | | } |
| | | |
| | | int rec::shrinkCache(){ |
| | | //超过最大缓存,丢弃gop |
| | | //缓存最小长度的,用于记录 |
| | | while (list_pkt_.size() > minduration_/2) { |
| | | 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) { |
| | | list_pkt_.pop_front(); |
| | | while(!list_pkt_.empty()){ |
| | | auto &cache = list_pkt_.front(); |
| | | AVPacket &avpkt = cache.data->getAVPacket(); |
| | | if (!(avpkt.flags & AV_PKT_FLAG_KEY)){ |
| | | auto &i = list_pkt_.front(); |
| | | if (!(i.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){ |
| | | list_pkt_.pop_front(); |
| | | }else{ |
| | | break; |