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