From 7fe46306ac577db11ba8a8bbf20653861fcb1a1a Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期二, 22 十月 2019 15:31:29 +0800 Subject: [PATCH] rec bug fix --- csrc/buz/recorder.cpp | 224 +++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 142 insertions(+), 82 deletions(-) diff --git a/csrc/buz/recorder.cpp b/csrc/buz/recorder.cpp index d3d9a98..4eb454c 100644 --- a/csrc/buz/recorder.cpp +++ b/csrc/buz/recorder.cpp @@ -24,19 +24,20 @@ ,out_(NULL) ,maxduration(30 * 25) ,minduration(10 * 25) - ,end_frame(minduration) - ,cur_frame(0) + ,fp_(NULL) ,stop_recorder_(false) ,id_(id) - ,id_frame_(-1) - ,id_frame_in_file_(-1) + ,id_frame_(0) + ,id_frame_in_file_(0) ,file_path_("") ,func_rec_info_(nullptr) ,thrd_(nullptr) - ,error_occured_(false) ,audio_(false) - ,cur_frame_a(0) - ,fp_(NULL) + ,end_frame_(0) + ,v_cur_frame_(0) + ,a_cur_frame_(0) + ,error_occured_(false) + ,last_rec_id_(-1) { if (in){ maxduration = 30 * in->getFPS(); @@ -91,14 +92,14 @@ } bool ret = out_->JustWriter(v, a, file_path_.c_str()); if (ret){ - logIt("start record file: %s", file_path_.c_str()); + logIt("start record h264 file: %s", file_path_.c_str()); return 0; }else{ file_path_ = "./" + filename; ret = out_->JustWriter(v, a, file_path_.c_str()); logIt("failed in dir %s, try file %s to start record file", dir_.c_str(), file_path_.c_str()); if (ret){ - logIt("start record file: %s", file_path_.c_str()); + logIt("start record h264 file: %s", file_path_.c_str()); return 0; } } @@ -114,7 +115,7 @@ } int pid = getpid(); - std::string filename(sole::uuid4().base62() + "-" + std::to_string(pid) + ".mp4"); + std::string filename(sole::uuid4().base62() + "-" + std::to_string(pid) + ".hevc"); file_path_ = dir_ + "/" + filename; fp_ = fopen(file_path_.c_str(), "wb"); @@ -127,7 +128,7 @@ return -1; } } - logIt("start record file: %s", file_path_.c_str()); + logIt("start record hevc file: %s", file_path_.c_str()); return 0; } @@ -149,27 +150,33 @@ //////////////////////// int Recorder::write_h264(const CPacket &pkt){ //reader failed, break stream - if(pkt.id == -1 && !pkt.data){ + if(!pkt.data){ return -1; } - if (cur_frame == end_frame){ + if (v_cur_frame_ == end_frame_){ return 1; } AVPacket &op = pkt.data->getAVPacket(); + + if (!audio_ && in_->isAudioPkt(&op)) { + return 0; + } + AVPacket np(op); av_copy_packet(&np, &op); - int64_t cur = cur_frame; + int64_t cur = v_cur_frame_; if (in_->isVideoPkt(&np)){ - if(pkt.id == id_frame_){ - id_frame_in_file_ = cur_frame; + if(pkt.v_id == id_frame_){ + id_frame_in_file_ = v_cur_frame_; } - cur_frame++; + v_cur_frame_++; + }else if (in_->isAudioPkt(&np)) { - cur = cur_frame_a++; + cur = a_cur_frame_++; } auto ret = out_->writeFrame(&np, cur); @@ -187,21 +194,31 @@ logIt("write hevc packet error, file not open"); return -1; } - if (cur_frame == end_frame){ + if (v_cur_frame_ == end_frame_){ return 1; } AVPacket &op = pkt.data->getAVPacket(); - int64_t cur = cur_frame; - if (in_->isVideoPkt(&op)){ - - if(pkt.id == id_frame_){ - id_frame_in_file_ = cur_frame; - } - cur_frame++; + + if (in_->isAudioPkt(&op)) { + return 0; + } + if (op.data == NULL){ + logIt("hevc avpacket data null"); + return 0; } + if (in_->isVideoPkt(&op)){ + + if(pkt.v_id == id_frame_){ + id_frame_in_file_ = v_cur_frame_; + } + v_cur_frame_++; + } fwrite(op.data, op.size, 1, fp_); + logIt("hevc write data len: %d frame id: %d key %d", + op.size, v_cur_frame_, op.flags & AV_PKT_FLAG_KEY); + return 0; } @@ -265,22 +282,27 @@ } int Recorder::mux_hevc(FILE *fp, const char *outfile){ - std::unique_ptr<FormatIn> in(new FormatIn(false)); if (!fp) { logIt("mux hevc file handle is null"); return -1; } + std::unique_ptr<FormatIn> in(nullptr); int tryTime = 0; - while (in->openWithCustomIO(fp, read_buffer) < 0) { - usleep(10000); - if (tryTime++ < 100){ - logIt("mux hevc mux: %d failed open custom io %s, try again", tryTime, outfile); - continue; + + while(true){ + std::unique_ptr<FormatIn> tmp(new FormatIn(false)); + auto ret = tmp->openWithCustomIO(fp, read_buffer); + if (ret == 0){ + in = std::move(tmp); + break; } - logIt("mux hevc try %d time to open custom io, failed", tryTime); - return -2; + usleep(10000); + if (tryTime++ > 100){ + logIt("mux hevc try %d time to open custom io %s, failed", tryTime, outfile); + return -2; + } } if (in->open(NULL, NULL) < 0){ logIt("mux hevc open stream error"); @@ -298,7 +320,7 @@ return -5; } if (out->JustWriter(v, NULL, outfile)){ - logIt("mux hevc start record file: %s", outfile); + logIt("mux hevc start record file: %s", outfile); } int64_t id = 0; @@ -327,13 +349,12 @@ end_write_h264(); } - logIt("finished record : %s frames: %d", file_path_.c_str(), cur_frame); + logIt("finished record : %s frames: %d, frame in file id: %d", + file_path_.c_str(), end_frame_, id_frame_in_file_); { std::lock_guard<std::mutex> l(mutex_pkt_); list_pkt_.clear(); } - // logIt("INDEX %d, REAL-FRAME-ID %d, FILE %s, CURFrame %d, ENDFrame %d\n", - // id_frame_in_file_, id_frame_, file_path_.c_str(), cur_frame, end_frame); if(func_rec_info_){ func_rec_info_(id_,id_frame_in_file_, file_path_); @@ -347,14 +368,17 @@ std::list<CPacket> pkts; { std::unique_lock<std::mutex> locker(mutex_pkt_); - auto status = cv_.wait_for(locker, std::chrono::seconds(3), [&]{ + int sec = minduration/50; + if (in_) sec = minduration/in_->getFPS()/2; + auto status = cv_.wait_for(locker, std::chrono::seconds(sec), [&]{ return !list_pkt_.empty() || stop_recorder_.load(); }); - + if (!status || stop_recorder_.load()){ error_occured_ = !status; break; } + list_pkt_.swap(pkts); } @@ -373,6 +397,7 @@ stop_recorder_.store(true); end_writer(); + list_pkt_.clear(); } int Recorder::Run(const char* output, const int mind, const int maxd, const bool audio){ @@ -391,12 +416,12 @@ if(fps > 1.0){ maxduration = fps * maxd; minduration = fps * mind; - end_frame = minduration; + end_frame_ = minduration; } audio_ = a; - logIt("minduration %d maxduration %d curduration %d", minduration, maxduration, end_frame); + logIt("minduration %d maxduration %d", minduration, maxduration); thrd_.reset(new std::thread([&]{ run_thread(); @@ -409,76 +434,111 @@ int Recorder::FireRecorder(const int64_t &id){ if (stop_recorder_.load()) return -1; - if(id_frame_ == -1){ + if(id_frame_ == 0){ id_frame_ = id; - + std::lock_guard<std::mutex> locker(mutex_pkt_); - if (list_pkt_.size() > end_frame){ - end_frame = list_pkt_.size() + minduration/2; - if (end_frame > maxduration) - end_frame = maxduration; + if (list_pkt_.size() > end_frame_){ + end_frame_ = list_pkt_.size() + minduration/2; + if (end_frame_ > maxduration) + end_frame_ = maxduration; } + + }else if(v_cur_frame_ > minduration/2 && end_frame_ < maxduration){ + logIt("cur frame: %d, end frame: %d, duration: [%d-%d]", + v_cur_frame_, end_frame_, minduration, maxduration); - // logIt("FIRST FIRE RECORD ID: %lld, cur_frame: %d, end_frame: %d", id, cur_frame, end_frame); - - }else if(cur_frame > minduration/2 && end_frame < maxduration){ - end_frame = end_frame + minduration / 2; - if(end_frame > maxduration){ - end_frame = maxduration; + end_frame_ = end_frame_ + minduration / 2; + if(end_frame_ > maxduration){ + end_frame_ = maxduration; } - // logIt("PROLONG REC, cur_frame: %d, end_frame: %d", cur_frame, end_frame); } - // logIt("FIRE REC FRAME ID: %lld", id); + return 0; } - int Recorder::PushPacket(const CPacket &pkt){ + int Recorder::PushPacket(std::list<CPacket> &lst){ if (stop_recorder_.load()) return 0; std::lock_guard<std::mutex> locker(mutex_pkt_); - - if(id_frame_ == -1){ - //wait I - if (!audio_ && in_->isAudioPkt(&pkt.data->getAVPacket())){ - return 0; + // 娌℃湁寮�濮嬪綍鍒� + if (last_rec_id_ < 0){ + logIt("last rec id is 0 cache size: %ld", lst.size()); + for (auto &i : lst){ + // 浠庣涓�涓潪闊抽鍏抽敭甯у紑濮� + if (last_rec_id_ < 0){ + if (!in_->isVideoPkt(&i.data->getAVPacket())){ + continue; + } + if (!(i.data->getAVPacket().flags & AV_PKT_FLAG_KEY)){ + continue; + } + } + last_rec_id_ = i.id; + list_pkt_.push_back(i); } - - maybe_dump_gop(); - - list_pkt_.push_back(pkt); - // cv_.notify_one(); - }else{ - list_pkt_.push_back(pkt); - cv_.notify_one(); + for(auto &i : lst){ + if (i.id > last_rec_id_){ + list_pkt_.push_back(i); + last_rec_id_++; + } + } } + + + cv_.notify_one(); return list_pkt_.size(); } - int Recorder::PushPackets(std::list<CPacket> &lst){ - + int Recorder::StartWritePacket(std::list<CPacket> &lst, const int64_t &id, const int start, const int end){ + if (stop_recorder_.load()) return 0; + // 绗竴娆″綍鍍�,璁剧疆瑙﹀彂甯d + id_frame_ = id; + + + if (start < 0) { + logIt("start write packet [%d-%d] in pkt size: %d, frame id: %lld, " + "cur frame: %d, end frame: %d, duration: [%d-%d], last rec id: %lld", + start, end, lst.size(), id_frame_, + v_cur_frame_, end_frame_, minduration, maxduration, last_rec_id_); + return -1; + } + std::lock_guard<std::mutex> locker(mutex_pkt_); - bool i = false; + // 灏嗕紶鍏ョ殑鎵�鏈塸ackets淇濆瓨濡傜紦瀛� + int index = -1; for (auto &p : lst){ - if (!audio_ && in_->isAudioPkt(&p.data->getAVPacket())){ - continue; - } + index++; + if (index < start) continue; list_pkt_.push_back(p); + + if (index == end){ + last_rec_id_ = p.id; + break; + } } - maybe_dump_gop(); + + + logIt("start write packet [%d-%d] in pkt size: %d, frame id: %lld, " + "cur frame: %d, end frame: %d, duration: [%d-%d], last rec id: %lld", + start, end, lst.size(), id_frame_, + v_cur_frame_, end_frame_, minduration, maxduration, last_rec_id_); + + + // maybe_dump_gop(); cv_.notify_one(); - // logIt("CACHE PACKET : %d", list_pkt_.size()); return list_pkt_.size(); } void Recorder::maybe_dump_gop(){ - //瓒呰繃min/2,涓㈠純gop - while (list_pkt_.size() > minduration) { + + while (list_pkt_.size() > maxduration) { list_pkt_.pop_front(); while(!list_pkt_.empty()){ auto &i = list_pkt_.front(); @@ -490,5 +550,5 @@ } } } - } -} + }// end clase +}// end namespace -- Gitblit v1.8.0