From 4587f8d5507300782e329f9527f35f905f3bb697 Mon Sep 17 00:00:00 2001
From: chenshijun <csj_sky@126.com>
Date: 星期二, 29 十月 2019 14:13:25 +0800
Subject: [PATCH] Merge branch 'master' of ssh://192.168.5.5:29418/valib/goffmpeg

---
 csrc/ffmpeg/configure/conf.cpp             |    2 
 godecjpeg.go                               |    2 
 csrc/thirdparty/gb28181/include/PsToEs.hpp |   16 +
 csrc/ffmpeg/format/FormatIn.cpp            |   39 +-
 csrc/ffmpeg/format/FormatOut.cpp           |    2 
 goconv.go                                  |    8 
 libcffmpeg.c                               |  184 +++++++----
 csrc/cffmpeg.cpp                           |   13 
 gorec.go                                   |   10 
 libcffmpeg.h                               |   48 +-
 csrc/common.hpp                            |    7 
 gostream.go                                |    2 
 cffmpeg.h                                  |    6 
 goenc.go                                   |    7 
 csrc/buz/recorder.hpp                      |   36 +-
 csrc/buz/recorder.cpp                      |  246 ++++++++++-----
 csrc/wrapper.cpp                           |   89 ++---
 godec.go                                   |    4 
 csrc/worker/rec.cpp                        |  106 +++++-
 csrc/worker/stream.cpp                     |   11 
 csrc/worker/decoder.cpp                    |    8 
 csrc/wrapper.hpp                           |   11 
 goffmpeg.go                                |   21 
 csrc/worker/rec.hpp                        |   14 
 csrc/worker/stream.hpp                     |    2 
 csrc/worker/decoder.hpp                    |    6 
 26 files changed, 538 insertions(+), 362 deletions(-)

diff --git a/cffmpeg.h b/cffmpeg.h
index ef67716..0a7ebd1 100644
--- a/cffmpeg.h
+++ b/cffmpeg.h
@@ -15,11 +15,12 @@
 void c_ffmpeg_destroy(const cffmpeg h);
 void c_ffmpeg_run(const cffmpeg h, const char *input);
 
+int c_ffmpeg_get_fps(const cffmpeg h);
 void c_ffmpeg_run_gb28181(const cffmpeg h);
 void c_ffmepg_use_cpu(const cffmpeg h);
 /////////passive api
 void c_ffmpeg_set_record_duration(const cffmpeg h, const int min, const int max);
-void c_ffmpeg_build_recorder(const cffmpeg h, const char*id, const char *dir, int mind, int maxd, int audio);
+void c_ffmpeg_build_recorder(const cffmpeg h, const char*id, const char *dir, const int64_t fid, int mind, int maxd, int audio);
 void c_ffmpeg_fire_recorder(const cffmpeg h, const char*sid, const int64_t id);
 void c_ffmpeg_get_info_recorder(const cffmpeg h, int *index, char** recid, int *recidLen, char **fpath, int *pathLen);
 
@@ -40,9 +41,6 @@
                           const int dstW, const int dstH, const int dstFormat, const int flag);
 void c_ffmpeg_destroy_conv(void *h);
 void *c_ffmpeg_conv(void *h, uint8_t *in);
-
-// gpu conv
-void* c_gpu_conv(uint8_t *in, const int w, const int h, const int dst_w, const int dst_h, int *length);
 
 #ifdef __cplusplus
 }
diff --git a/csrc/buz/recorder.cpp b/csrc/buz/recorder.cpp
index d3d9a98..beda224 100644
--- a/csrc/buz/recorder.cpp
+++ b/csrc/buz/recorder.cpp
@@ -5,6 +5,8 @@
 #include <unistd.h>
 #include <chrono>
 
+#include <sys/stat.h>
+
 extern "C"{
 #include <libavcodec/avcodec.h>
 }
@@ -24,19 +26,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();
@@ -81,6 +84,12 @@
             std::string filename(sole::uuid4().base62() + "-" + std::to_string(pid) + ".mp4");
             file_path_ = dir_ + "/" + filename;
 
+            std::string backup_dir("./video");
+            size_t pos = dir_.rfind("/");
+            if (pos != std::string::npos){
+                backup_dir = dir_.substr(0, pos);
+            }
+
             auto v = in_->getStream(AVMEDIA_TYPE_VIDEO);
             if (!v){
                 return -2;
@@ -91,14 +100,16 @@
             }
             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());
+                mkdir(backup_dir.c_str(), 0777);
+                file_path_ = backup_dir + "/" + filename;
+
                 logIt("failed in dir %s, try file %s to start record file", dir_.c_str(), file_path_.c_str());                
+                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;
                 }
             }
@@ -114,12 +125,20 @@
             }
 
             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;
 
+            std::string backup_dir("./video");
+            size_t pos = dir_.rfind("/");
+            if (pos != std::string::npos){
+                backup_dir = dir_.substr(0, pos);
+            }
+            
             fp_ = fopen(file_path_.c_str(), "wb");
             if (!fp_){
-                file_path_ = "./" + filename;
+                mkdir(backup_dir.c_str(), 0777);
+                file_path_ = backup_dir + "/" + filename;
+
                 logIt("failed in dir %s, try file %s to start record hevc file", dir_.c_str(), file_path_.c_str());                
                 fp_ = fopen(file_path_.c_str(), "wb");
                 if (!fp_){
@@ -127,7 +146,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 +168,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 +212,29 @@
                 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_); 
+
             return 0;
         }
 
@@ -265,22 +298,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 +336,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 +365,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 +384,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 +413,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 +432,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 +450,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 +566,5 @@
                 }
             }
         }
-    }
-}
+    }// end clase
+}// end namespace
diff --git a/csrc/buz/recorder.hpp b/csrc/buz/recorder.hpp
index 9c88bbb..9cb557a 100644
--- a/csrc/buz/recorder.hpp
+++ b/csrc/buz/recorder.hpp
@@ -32,8 +32,8 @@
 
             public: 
                 int Run(const char* output, const int mind, const int maxd, const bool audio);
-                int PushPacket(const CPacket &pkt);
-                int PushPackets(std::list<CPacket> &lst);
+                int PushPacket(std::list<CPacket> &lst);
+                int StartWritePacket(std::list<CPacket> &lst, const int64_t &id, const int start, const int end);
                 int FireRecorder(const int64_t &id);
 
                 void SetCallback(FUNC_REC_INFO cb){
@@ -63,33 +63,33 @@
                 ffwrapper::FormatIn     *in_;
                 ffwrapper::FormatOut    *out_;
 
-                int     maxduration;
-                int     minduration;
-                int     end_frame;
-                int     cur_frame;
-                int     cur_frame_a;
-
-                std::list<CPacket>     list_pkt_;
-
+                std::list<CPacket>      list_pkt_;
                 std::atomic_bool        stop_recorder_;
                 std::mutex              mutex_pkt_;
      		    std::condition_variable cv_;
-
-                std::unique_ptr<std::thread> thrd_;
-                
                 std::string             dir_;
                 std::string             id_;
-
                 int64_t                 id_frame_;
                 int                     id_frame_in_file_;
+
                 std::string             file_path_;
                 FUNC_REC_INFO           func_rec_info_;
-
-                bool                    error_occured_;
-
+                FILE                    *fp_;
                 bool                    audio_;
 
-                FILE                    *fp_;
+                std::unique_ptr<std::thread> thrd_;
+
+
+                int     end_frame_;
+                int     v_cur_frame_;
+                int     a_cur_frame_;
+                
+                int64_t last_rec_id_;
+
+                int     maxduration;
+                int     minduration;
+
+                bool                    error_occured_;
         };
     }
 }
diff --git a/csrc/cffmpeg.cpp b/csrc/cffmpeg.cpp
index 690f061..4cf92da 100644
--- a/csrc/cffmpeg.cpp
+++ b/csrc/cffmpeg.cpp
@@ -33,6 +33,11 @@
     s->RunStream(input);
 }
 
+int c_ffmpeg_get_fps(const cffmpeg h){
+    Wrapper *s = (Wrapper*)h;
+    return s->GetFPS();
+}
+
 void c_ffmpeg_run_gb28181(const cffmpeg h){
     Wrapper *s = (Wrapper*)h;
     s->GB28181();
@@ -50,11 +55,11 @@
     s->SetRecMinCacheTime(min);
 }
 
-void c_ffmpeg_build_recorder(const cffmpeg h, const char* id, const char *dir, int mind, int maxd, int audio){
+void c_ffmpeg_build_recorder(const cffmpeg h, const char* id, const char *dir, const int64_t fid, int mind, int maxd, int audio){
     Wrapper *s = (Wrapper*)h;
 
     bool a = audio == 0 ? false : true;
-    s->BuildRecorder(id, dir, mind, maxd, a);
+    s->BuildRecorder(id, dir, fid, mind, maxd, a);
 }
 
 void c_ffmpeg_fire_recorder(const cffmpeg h, const char* sid, const int64_t id){
@@ -134,7 +139,3 @@
 void c_ffmpeg_destroy_conv(void *h){
     DestoryConvertor(h);
 }
-
-void* c_gpu_conv(uint8_t *in, const int w, const int h, const int dst_w, const int dst_h, int *length){
-    return ConvertYUV2BGR(in, w, h, dst_w, dst_h, length);
-}
\ No newline at end of file
diff --git a/csrc/common.hpp b/csrc/common.hpp
index e2a6064..2495bd5 100644
--- a/csrc/common.hpp
+++ b/csrc/common.hpp
@@ -8,9 +8,12 @@
     class CodedData;
 }
 // 缂撳瓨鐨勮棰戝抚
-typedef struct _cache_pkt{
+class CPacket{
+public:
     std::shared_ptr<ffwrapper::CodedData> data;
+    int64_t v_id;
+    int64_t a_id;
     int64_t id;
-}CPacket;
+};
 
 #endif
\ No newline at end of file
diff --git a/csrc/ffmpeg/configure/conf.cpp b/csrc/ffmpeg/configure/conf.cpp
index 43e45ac..d836840 100644
--- a/csrc/ffmpeg/configure/conf.cpp
+++ b/csrc/ffmpeg/configure/conf.cpp
@@ -13,7 +13,7 @@
 	    av_register_all();
         avfilter_register_all();
         avformat_network_init();
-        av_log_set_level(AV_LOG_VERBOSE);
+        av_log_set_level(AV_LOG_ERROR);
 	}
 
 	std::string getAVErrorDesc(const int code){
diff --git a/csrc/ffmpeg/format/FormatIn.cpp b/csrc/ffmpeg/format/FormatIn.cpp
index 9f743f8..59f3f23 100644
--- a/csrc/ffmpeg/format/FormatIn.cpp
+++ b/csrc/ffmpeg/format/FormatIn.cpp
@@ -38,20 +38,13 @@
 
 	FormatIn::~FormatIn()
 	{
-		if(io_ctx_){
-			if(read_io_buff_){
-				// av_free(read_io_buff_);
-				read_io_buff_ = NULL;
-			}
-			avio_context_free(&io_ctx_);
-			io_ctx_ = NULL;
-		}
 		if(ctx_){
-			if (!ctx_->oformat){
-				avformat_free_context(ctx_);
-			}else{
+			if (!(ctx_->flags & AVFMT_FLAG_CUSTOM_IO)){
 				avformat_close_input(&ctx_);
+			}else{
+				avformat_free_context(ctx_);
 			}
+
 			ctx_ = NULL;
 			if(dec_ctx_){
 				avcodec_close(dec_ctx_);
@@ -59,18 +52,23 @@
 			}
 			
 		}
+		
 		if (handle_gb28181){
 			delete handle_gb28181;
 		}
+		if(read_io_buff_){
+			av_free(read_io_buff_);
+			read_io_buff_ = NULL;
+		}
+		if(io_ctx_){
+			avio_context_free(&io_ctx_);
+			io_ctx_ = NULL;
+		}
+
 	}
 
 ////////////////////////////////////////////////////////////////////////
 	int FormatIn::openWithCustomIO(void *opaque, read_packet fn, AVDictionary **options/*=NULL*/){
-		ctx_ = avformat_alloc_context();
-		if(!ctx_){
-			logIt("open with custom io create format error\n");
-			return -1;
-		}
 		read_io_buff_ = (uint8_t*)av_malloc(read_io_buff_size_);
 		if(!read_io_buff_){
 			logIt("open with custom io alloc read io buff error\n");
@@ -82,9 +80,16 @@
 			logIt("open with custom io create custom avio error\n");
 			return -1;
 		}
+		
+		ctx_ = avformat_alloc_context();
+		if(!ctx_){
+			logIt("open with custom io create format error\n");
+			return -1;
+		}
+
 		ctx_->pb = io_ctx_;
 
-		auto err = av_probe_input_buffer(ctx_->pb, &ctx_->iformat, NULL, NULL, 0, read_io_buff_size_);
+		auto err = av_probe_input_buffer(ctx_->pb, &ctx_->iformat, NULL, NULL, 0, 0);
 		if(err != 0){
 			logIt("open with custom io prob input buffer error:%d err: %s\n", err, getAVErrorDesc(err).c_str());
 			return -1;
diff --git a/csrc/ffmpeg/format/FormatOut.cpp b/csrc/ffmpeg/format/FormatOut.cpp
index 60efd59..e832bfe 100644
--- a/csrc/ffmpeg/format/FormatOut.cpp
+++ b/csrc/ffmpeg/format/FormatOut.cpp
@@ -399,7 +399,7 @@
         int out_idx = -1;
         std::vector<AVStream*> in_streams{in_v_stream_, in_a_stream_};
         for (auto i : in_streams){
-            if (i->index == pkt->stream_index){
+            if (i && (i->index == pkt->stream_index)){
                 if (i->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
                     out_idx = v_idx_;
                     in_stream = i;
diff --git a/csrc/thirdparty/gb28181/include/PsToEs.hpp b/csrc/thirdparty/gb28181/include/PsToEs.hpp
index df0c2ed..4c10a28 100644
--- a/csrc/thirdparty/gb28181/include/PsToEs.hpp
+++ b/csrc/thirdparty/gb28181/include/PsToEs.hpp
@@ -75,6 +75,16 @@
 		while (!q.empty()) q.pop_front();
 		pthread_mutex_unlock(&mtx);
     }
+	
+	void clearAll(std::function<void(T)> fn){
+		pthread_mutex_lock(&mtx);
+		while (!q.empty()){
+			T value = q.front();
+			fn(value);
+			q.pop_front();
+		} 
+		pthread_mutex_unlock(&mtx);
+	}
 private:
     deque<T> q;
     pthread_mutex_t mtx;
@@ -96,7 +106,11 @@
 
 	~GB28181API(){
 		printf("GB28181API end!\n");
-		m_rtpQueue.clearAll();
+		// m_rtpQueue.clearAll();
+		m_rtpQueue.clearAll([](frameBuffInfo *info){
+			delete[] info->buff;
+			delete info;
+		});
 		deleteCamera();
 	}
 
diff --git a/csrc/worker/decoder.cpp b/csrc/worker/decoder.cpp
index f5e95b5..558d871 100644
--- a/csrc/worker/decoder.cpp
+++ b/csrc/worker/decoder.cpp
@@ -4,6 +4,7 @@
 #include "../ffmpeg/format/FormatIn.hpp"
 #include "../ffmpeg/data/CodedData.hpp"
 #include "../ffmpeg/log/log.hpp"
+#include "../common.hpp"
 
 extern "C"{
 #include <libavformat/avformat.h>
@@ -46,7 +47,7 @@
         return 0;
     }
 
-    int decoder::saveFrame(AVFrame *frame, int64_t &id){
+    int decoder::saveFrame(AVFrame *frame, const int64_t &id){
         FRM frm;
         frm.width = frame->width;
         frm.height = frame->height;
@@ -67,7 +68,8 @@
         return list_frm_.size();   
     }
 
-    int decoder::SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){
+    int decoder::SetFrame(const CPacket &pkt){
+        auto data = pkt.data;
 
         if (!data) return -10;
         if (!decRef_->isVideoPkt(&data->getAVPacket())) return -20;
@@ -83,7 +85,7 @@
         av_packet_unref(&np);
         
         if (ret == 0){
-            saveFrame(frame, id);
+            saveFrame(frame, pkt.v_id);
         }
         av_frame_free(&frame);
         return ret;
diff --git a/csrc/worker/decoder.hpp b/csrc/worker/decoder.hpp
index d157d25..a1946bd 100644
--- a/csrc/worker/decoder.hpp
+++ b/csrc/worker/decoder.hpp
@@ -12,6 +12,8 @@
 struct AVFrame;
 struct AVCodecContext;
 
+class CPacket;
+
 namespace ffwrapper
 {
     class FormatIn;
@@ -40,10 +42,10 @@
         
     private:
         int initDecoder();
-        int saveFrame(AVFrame *frame, int64_t &id);
+        int saveFrame(AVFrame *frame, const int64_t &id);
     public: 
         void Start();
-        int SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id);
+        int SetFrame(const CPacket &pkt);
         void GetFrame(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id);
     
     public:
diff --git a/csrc/worker/rec.cpp b/csrc/worker/rec.cpp
index 2e02903..9c5ae1e 100644
--- a/csrc/worker/rec.cpp
+++ b/csrc/worker/rec.cpp
@@ -16,12 +16,13 @@
 using namespace ffwrapper;
 using namespace cffmpeg_wrap::buz;
 
+static const int cache_time = 6 * 60;
+
 namespace cffmpeg_wrap
 {
     rec::rec()
     :recRef_(NULL)
-    ,min_cache_len_(125)
-    ,time_offset_(5)
+    ,min_cache_len_(cache_time * 25) // 鏈�灏忕紦瀛�?鍒嗛挓鐨勮棰�,鍥犱负鏁翠釜娴佺▼浼氭湁寤惰繜,鏆傚畾?鍒嗛挓
     {}
 
     rec::~rec()
@@ -44,7 +45,49 @@
         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){
+    void rec::findRecFramesIndex(const int64_t &fired_id, const int duration, int &start, int &end){
+
+        start = end = -1;
+
+        if (list_pkt_.empty()){
+            return;
+        }
+        
+        // 褰曞儚寮�濮媔d鍦ㄨЕ鍙慽d涔嬪墠1/2鏃堕暱,淇濊瘉鍦ㄤ腑闂�
+        int64_t start_id = fired_id - duration/2;
+        // 瀵绘壘鍏抽敭甯т綔涓哄綍鍍忓紑濮媔d
+        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){
+                    // 褰撳墠甯d > 寮�濮媔d鎴栧紑濮媔d鍦╫ffset鍐�,浣滀负璧峰褰曞儚甯�
+                    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");
             return nullptr;
@@ -62,9 +105,17 @@
             if(ret == 0) break;
             usleep(200000);
         }
+        
         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(){
@@ -137,7 +191,7 @@
         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);
         
@@ -146,7 +200,7 @@
             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);
         }
         
     }
@@ -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);
 
         // 瓒呰繃缂撳瓨鏈�澶ч暱搴�,鍒犻櫎涓�涓猤op
         shrinkCache();
@@ -200,24 +259,21 @@
         if (recRef_){
             fps = recRef_->getFPS();
         }
-        min_cache_len_ = (min + time_offset_) * fps;
+        min_cache_len_ += min * fps;
     }
 
     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;
diff --git a/csrc/worker/rec.hpp b/csrc/worker/rec.hpp
index c802d9a..fc6ba0d 100644
--- a/csrc/worker/rec.hpp
+++ b/csrc/worker/rec.hpp
@@ -9,6 +9,7 @@
 #include "../buz/recorder.hpp"
 
 struct AVPacket;
+class CPacket;
 
 namespace ffwrapper
 {
@@ -24,8 +25,6 @@
     private:
         ffwrapper::FormatIn *recRef_;
         int min_cache_len_;
-        // 鏁翠釜娴佺▼鑰楁椂琛ュ伩褰曞埗鏃堕棿,2s榛樿
-        const int time_offset_;
         // 褰曞儚鐨勫疄渚�,瀵瑰簲浠诲姟
         std::unordered_map<std::string, std::unique_ptr<buz::Recorder> > map_rec_;
         // 澶氱嚎绋嬫坊鍔犱换鍔″疄渚�,鍦ㄨ娴佺嚎绋嬩娇鐢ㄥ綍鍍�,浣嗘槸娣诲姞鍦ㄥ彟涓�涓嚎绋�
@@ -47,25 +46,28 @@
         std::mutex mtx_pkt_;
 
     private: 
+        // 鏌ユ壘缂撳瓨涓殑褰曞埗甯�
+        void findRecFramesIndex(const int64_t &fired_id, const int duration, int &start, int &end);
+
         // 褰曞儚瀹炰緥鐨勫洖璋冨嚱鏁�,褰曞儚瀹屾垚鍚庤缃綍鍍忔枃浠惰矾寰�,id鍜屽抚id
         void setRecInfo(std::string &id, int &index, std::string &path);
         // 缂撳瓨瑙嗛鍖�
-        void cachePacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id);
+        void cachePacket(const CPacket &pkt);
         // 涓㈠純缂撳瓨
         int shrinkCache();
         // 鍒涘缓褰曞儚瀹炰緥寮�濮嬪綍鍍�
-        std::unique_ptr<buz::Recorder> startRec(std::string id, std::string dir, const int mind, const int maxd, const bool audio);
+        std::unique_ptr<buz::Recorder> startRec(std::string id, std::string dir, const int64_t &frameID, const int mind, const int maxd, const bool audio);
         // 娓呴櫎缂撳瓨,鏂嚎閲嶈繛鏃堕渶瑕�
         void clear();
     public:
-        void NewRec(const char* id, const char *output, const int mindur, const int maxdur, const bool audio);
+        void NewRec(const char* id, const char *output, const int64_t &frameID, const int mindur, const int maxdur, const bool audio);
 
         // 鍑嗗濂藉綍鍍�
         void Load(ffwrapper::FormatIn *in);
         void Unload();
         const bool Loaded() const;
         // 缂撳瓨褰曞儚鐨勮棰戝寘,绛夊緟瑙﹀彂褰曞儚,鎴栫洿鎺ユ斁鍒板綍鍍忕紦瀛�
-        void SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id);
+        void SetPacket(const CPacket &pkt);
         // 瑙﹀彂褰曞儚
         void FireRecSignal(const char* sid,const int64_t &id);
         // 鑾峰彇褰曞儚鏂囦欢璺緞鍜屽抚id
diff --git a/csrc/worker/stream.cpp b/csrc/worker/stream.cpp
index 9fe11da..94e5ac3 100644
--- a/csrc/worker/stream.cpp
+++ b/csrc/worker/stream.cpp
@@ -6,6 +6,8 @@
 
 #include "../ffmpeg/format/FormatIn.hpp"
 #include "../ffmpeg/data/CodedData.hpp"
+#include "../ffmpeg/log/log.hpp"
+using namespace logif;
 
 namespace cffmpeg_wrap{
     stream::stream(ffwrapper::FormatIn *in, const int maxSize)
@@ -19,16 +21,15 @@
         list_pkt_.clear();
     }
 
-    int stream::SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){
-        if (data){
-
+    int stream::SetPacket(const CPacket &pkt){
+        if (pkt.data){
             // 濡傛灉鍖呮槸闊抽鍖�,浣嗘槸涓嶄娇鐢ㄩ煶棰�,鐩存帴杩斿洖
-            if (!audio_ && streamRef_->isAudioPkt(&data->getAVPacket())){
+            if (!audio_ && streamRef_->isAudioPkt(&pkt.data->getAVPacket())){
                 return 0;
             }
             
             std::lock_guard<std::mutex> locker(mutex_avpkt_);
-            list_pkt_.push_back({data, id});
+            list_pkt_.push_back(pkt);
             
             while(list_pkt_.size() > max_size_/2*3){
                 list_pkt_.pop_front();
diff --git a/csrc/worker/stream.hpp b/csrc/worker/stream.hpp
index 5c75d26..8a0feec 100644
--- a/csrc/worker/stream.hpp
+++ b/csrc/worker/stream.hpp
@@ -24,7 +24,7 @@
         stream(ffwrapper::FormatIn *in, const int maxSize);
         ~stream();
 
-        int SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id);
+        int SetPacket(const CPacket &pkt);
         void GetPacket(unsigned char **pktData, int *size, int *key);
         void AudioSwitch(const bool a){audio_ = a;}
     };
diff --git a/csrc/wrapper.cpp b/csrc/wrapper.cpp
index fe6d576..86662a1 100644
--- a/csrc/wrapper.cpp
+++ b/csrc/wrapper.cpp
@@ -24,8 +24,7 @@
 #include "worker/stream.hpp"
 #include "worker/decoder.hpp"
 #include "worker/rec.hpp"
-
-#include "CUDALERP.h"
+#include "common.hpp"
 
 using namespace logif;
 using namespace ffwrapper;
@@ -53,6 +52,7 @@
     ,decoder_(nullptr)
     ,rec_(new rec)
     ,logit_(false)
+    ,fps_(25)
     {
         makeTheWorld();
     }
@@ -160,15 +160,15 @@
         }
     }
     
-    int Wrapper::run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){
+    int Wrapper::run_worker(ffwrapper::FormatIn *in, const CPacket &pkt){
         if (gb_){
-            AVPacket &pkt = data->getAVPacket();
-            pkt.pts = pkt.dts = AV_NOPTS_VALUE;
+            AVPacket &p = pkt.data->getAVPacket();
+            p.pts = p.dts = AV_NOPTS_VALUE;
         }
         int flag = 0;
-        if (stream_) stream_->SetPacket(data, id);
-        if (decoder_ && run_dec_) flag = decoder_->SetFrame(data, id);
-        if (rec_->Loaded()) rec_->SetPacket(data, id);
+        if (stream_) stream_->SetPacket(pkt);
+        if (decoder_ && run_dec_) flag = decoder_->SetFrame(pkt);
+        if (rec_->Loaded()) rec_->SetPacket(pkt);
 
         return flag;
     }
@@ -190,6 +190,8 @@
                 continue;
             }
 
+            fps_ = in->getFPS();
+            
             int wTime = 1000000.0 / in->getFPS() ;
             wTime >>= 1;
             logIt("WAIT TIME PER FRAME: %d", wTime);
@@ -197,7 +199,9 @@
             init_worker(in.get());
 
             int64_t id = gb_ ? 0 : -1;
-            
+            int64_t v_id = id;
+            int64_t a_id = id;
+
             bool exist = access(input_url_.c_str(), 0) == 0 ? true : false;
 
             while(!stop_stream_.load()){
@@ -206,25 +210,34 @@
                     logIt("read packet error, id: %lld", id);
                     break;
                 }
+                // 闈為煶瑙嗛
                 if (in->notVideoAudio(&data->getAVPacket())){
                     continue;
                 }
-
+                // 闈炲浗鏍囪烦杩囩涓�甯�,娴嬭瘯绗竴甯ф湁闂
                 if (!gb_ && id < 0){
-                    id++;
+                    id++; v_id++; a_id++;
                     continue;
                 }
-
+                CPacket pkt{data, v_id, a_id, id};
     	        // decode error
-                if (run_worker(in.get(), data, id) == -1){
+                if (run_worker(in.get(), pkt) == -1){
                     break;
                 }
 
+                if (in->isVideoPkt(&data->getAVPacket())){
+                    v_id++;
+                }else{
+                    a_id++;
+                }
+
+                id++;
+
+                //鏈湴鏂囦欢澶揩sleep涓�涓�
                 if (exist){
                     usleep(wTime);
                 }
 
-                id++;
             }
 
             deinit_worker();
@@ -235,16 +248,16 @@
         rec_->SetRecMinCacheTime(mind);
     }
 
-    void Wrapper::BuildRecorder(const char* id, const char *output, const int mindur, const int maxdur, const bool audio){
+    void Wrapper::BuildRecorder(const char* id, const char *output, const int64_t &fid, const int mindur, const int maxdur, const bool audio){
         bool a = audio;
         if (gb_) a = false;
-
+        
         if (rec_->Loaded()){
-            rec_->NewRec(id, output, mindur, maxdur, a);
+            rec_->NewRec(id, output, fid, mindur, maxdur, a);
         }else{
             std::string rid(id), dir(output);
             fn_rec_lazy_ = 
-            [=]{rec_->NewRec(rid.c_str(), dir.c_str(), mindur, maxdur, a);};
+            [=]{rec_->NewRec(rid.c_str(), dir.c_str(), fid, mindur, maxdur, a);};
         }
     }
 
@@ -488,45 +501,5 @@
         free(c);
     }
 
-
-    uint8_t* ConvertYUV2BGR(uint8_t *src, const int w, const int h, const int dst_w, const int dst_h, int *length){
-        return NULL;
-
-        // int oldw = w, oldh = h, neww = dst_w, newh = dst_h;
-        // 	// setting cache and shared modes
-	    // cudaDeviceSetCacheConfig(cudaFuncCachePreferL1);
-	    // cudaDeviceSetSharedMemConfig(cudaSharedMemBankSizeFourByte);
-
-	    // // allocating and transferring image and binding to texture object
-	    // cudaChannelFormatDesc chandesc_img = cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindUnsigned);
-	    // cudaArray* d_img_arr;
-	    // cudaMallocArray(&d_img_arr, &chandesc_img, oldw, oldh, cudaArrayTextureGather);
-	    // cudaMemcpyToArray(d_img_arr, 0, 0, image, oldh * oldw, cudaMemcpyHostToDevice);
-	    // struct cudaResourceDesc resdesc_img;
-	    // memset(&resdesc_img, 0, sizeof(resdesc_img));
-	    // resdesc_img.resType = cudaResourceTypeArray;
-	    // resdesc_img.res.array.array = d_img_arr;
-	    // struct cudaTextureDesc texdesc_img;
-	    // memset(&texdesc_img, 0, sizeof(texdesc_img));
-	    // texdesc_img.addressMode[0] = cudaAddressModeClamp;
-	    // texdesc_img.addressMode[1] = cudaAddressModeClamp;
-	    // texdesc_img.readMode = cudaReadModeNormalizedFloat;
-	    // texdesc_img.filterMode = cudaFilterModePoint;
-	    // texdesc_img.normalizedCoords = 0;
-	    // cudaTextureObject_t d_img_tex = 0;
-	    // cudaCreateTextureObject(&d_img_tex, &resdesc_img, &texdesc_img, nullptr);
-
-	    // uint8_t* d_out = nullptr;
-	    // cudaMalloc(&d_out, total);
-
-	    // for (int i = 0; i < warmups; ++i) CUDALERP(d_img_tex, oldw, oldh, d_out, neww, newh);
-	    // auto start = high_resolution_clock::now();
-	    // for (int i = 0; i < runs; ++i) CUDALERP(d_img_tex, oldw, oldh, d_out, neww, newh);
-	    // auto end = high_resolution_clock::now();
-	    // auto sum = (end - start) / runs;
-
-	    // auto h_out = new uint8_t[neww * newh];
-	    // cudaMemcpy(h_out, d_out, total, cudaMemcpyDeviceToHost);
-    }
 }
 
diff --git a/csrc/wrapper.hpp b/csrc/wrapper.hpp
index 4ae1a4f..73da823 100644
--- a/csrc/wrapper.hpp
+++ b/csrc/wrapper.hpp
@@ -11,7 +11,7 @@
 #include <memory>
 #include "common/callback.hpp"
 
-
+class CPacket;
 
 namespace ffwrapper{
     class FormatIn;
@@ -34,14 +34,14 @@
         std::unique_ptr<ffwrapper::FormatIn> init_reader(const char* input);
 
         void init_worker(ffwrapper::FormatIn *in);
-        int run_worker(ffwrapper::FormatIn *in, std::shared_ptr<ffwrapper::CodedData> data, int64_t &id);
+        int run_worker(ffwrapper::FormatIn *in, const CPacket &pkt);
         void deinit_worker();
     public: 
         int RunStream(const char* input);
     private: 
         void run_stream_thread();
     public: //recorder
-        void BuildRecorder(const char* id,const char *dir, const int mind, const int maxd, const bool audio);
+        void BuildRecorder(const char* id, const char *dir, const int64_t &fid, const int mind, const int maxd, const bool audio);
         int FireRecorder(const char* sid,const int64_t &id);
         void GetInfoRecorder(std::string &recID, int &index, std::string &path);
     
@@ -50,6 +50,8 @@
         void CPUDec(){cpu_ = 1;}
         void AudioSwitch(const bool a);
         void SetRecMinCacheTime(const int mind);
+
+        int GetFPS(){return fps_;}
     public: //decoder
         void BuildDecoder();
         void GetPicDecoder(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id);
@@ -74,6 +76,7 @@
         // 褰曞儚璇锋眰缂撳瓨,绛夊緟runstream鍚庢坊鍔�
         std::function<void()> fn_rec_lazy_;
         bool logit_;
+        int fps_;
     };
 
     uint8_t* Decode(const char *file, const int gb, int *w, int *h);
@@ -86,8 +89,6 @@
                           const int dstW, const int dstH, const int dstFormat, const int flag);
     uint8_t *Convert(void *h, uint8_t *src);
     void DestoryConvertor(void *h);
-
-    uint8_t* ConvertYUV2BGR(uint8_t *src, const int w, const int h, const int dst_w, const int dst_h, int *length);
 }
 
 #endif
\ No newline at end of file
diff --git a/goconv.go b/goconv.go
index 55869ba..06dba30 100644
--- a/goconv.go
+++ b/goconv.go
@@ -52,7 +52,7 @@
 
 // NewConv new conv
 func NewConv(srcW, srcH, dstW, dstH, scaleFlag int) *GoConv {
-	c := C.wrap_fn_create_conv(C.int(srcW), C.int(srcH), C.int(SrcFormat),
+	c := C.wrap_fn_create_conv(unsafe.Pointer(libcffmpeg), C.int(srcW), C.int(srcH), C.int(SrcFormat),
 		C.int(dstW), C.int(dstH), C.int(DstFormat), C.int(scaleFlag))
 
 	if c == nil {
@@ -70,7 +70,7 @@
 
 // NewResizer resize
 func NewResizer(srcW, srcH, format, dstW, dstH, scaleFlag int) *GoConv {
-	c := C.wrap_fn_create_conv(C.int(srcW), C.int(srcH), C.int(format),
+	c := C.wrap_fn_create_conv(unsafe.Pointer(libcffmpeg), C.int(srcW), C.int(srcH), C.int(format),
 		C.int(dstW), C.int(dstH), C.int(format), C.int(scaleFlag))
 
 	if c == nil {
@@ -89,7 +89,7 @@
 // Free free
 func (c *GoConv) Free() {
 	if c.conv != nil {
-		C.wrap_fn_destroy_conv(c.conv)
+		C.wrap_fn_destroy_conv(unsafe.Pointer(libcffmpeg), c.conv)
 	}
 }
 
@@ -102,7 +102,7 @@
 	cin := C.CBytes(src)
 	defer C.free(cin)
 
-	bgr := C.wrap_fn_conv(c.conv, (*C.uchar)(cin))
+	bgr := C.wrap_fn_conv(unsafe.Pointer(libcffmpeg), c.conv, (*C.uchar)(cin))
 	defer C.free(unsafe.Pointer(bgr))
 
 	if bgr != nil {
diff --git a/godec.go b/godec.go
index a232618..aab8c7a 100644
--- a/godec.go
+++ b/godec.go
@@ -9,7 +9,7 @@
 
 // BuildDecoder build decoder
 func (h *GoFFMPEG) BuildDecoder() {
-	C.wrap_fn_decoder(h.ffmpeg)
+	C.wrap_fn_decoder(unsafe.Pointer(libcffmpeg), h.ffmpeg)
 }
 
 // GetYUV get yuv data
@@ -18,7 +18,7 @@
 	var length C.int
 	var srcW, srcH, srcF C.int
 
-	p := C.wrap_fn_decoder_pic(h.ffmpeg, &srcW, &srcH, &srcF, &length, &fid)
+	p := C.wrap_fn_decoder_pic(unsafe.Pointer(libcffmpeg), h.ffmpeg, &srcW, &srcH, &srcF, &length, &fid)
 	if srcW == 0 || srcH == 0 {
 		return nil, 0, 0, 0
 	}
diff --git a/godecjpeg.go b/godecjpeg.go
index 6cc855d..6cef6af 100644
--- a/godecjpeg.go
+++ b/godecjpeg.go
@@ -23,7 +23,7 @@
 
 	var width C.int
 	var height C.int
-	p := C.wrap_fn_decode(in, C.int(withGB), &width, &height)
+	p := C.wrap_fn_decode(unsafe.Pointer(libcffmpeg), in, C.int(withGB), &width, &height)
 	defer C.free(p)
 
 	if width > 0 && height > 0 {
diff --git a/goenc.go b/goenc.go
index 3d00996..d7a6b43 100644
--- a/goenc.go
+++ b/goenc.go
@@ -5,6 +5,7 @@
 #include "libcffmpeg.h"
 */
 import "C"
+import "unsafe"
 
 ///////////////for encoder
 
@@ -20,14 +21,14 @@
 	}
 
 	return &GoEncoder{
-		enc: C.wrap_fn_create_encoder(C.int(w), C.int(h), C.int(fps), C.int(br), C.int(sFlag), C.int(gi)),
+		enc: C.wrap_fn_create_encoder(unsafe.Pointer(libcffmpeg), C.int(w), C.int(h), C.int(fps), C.int(br), C.int(sFlag), C.int(gi)),
 	}
 }
 
 // Free free
 func (e *GoEncoder) Free() {
 	if e.enc != nil {
-		C.wrap_fn_destroy_encoder(e.enc)
+		C.wrap_fn_destroy_encoder(unsafe.Pointer(libcffmpeg), e.enc)
 	}
 }
 
@@ -39,7 +40,7 @@
 	cin := C.CBytes(in)
 	defer C.free(cin)
 
-	p := C.wrap_fn_encode(e.enc, cin, C.int(w), C.int(h), &size, &key)
+	p := C.wrap_fn_encode(unsafe.Pointer(libcffmpeg), e.enc, cin, C.int(w), C.int(h), &size, &key)
 	defer C.free(p)
 	if p != nil && size > 0 {
 		b := C.GoBytes(p, size)
diff --git a/goffmpeg.go b/goffmpeg.go
index dedb2bf..efaf6cc 100644
--- a/goffmpeg.go
+++ b/goffmpeg.go
@@ -42,16 +42,16 @@
 // New 2nd new
 func New(GB, CPU bool) *GoFFMPEG {
 
-	f := C.wrap_fn_create()
+	f := C.wrap_fn_create(unsafe.Pointer(libcffmpeg))
 
 	if f == nil {
 		return nil
 	}
 	if GB {
-		C.wrap_fn_run_gb28181(f)
+		C.wrap_fn_run_gb28181(unsafe.Pointer(libcffmpeg), f)
 	}
 	if CPU {
-		C.wrap_fn_use_cpu(f)
+		C.wrap_fn_use_cpu(unsafe.Pointer(libcffmpeg), f)
 	}
 
 	return &GoFFMPEG{
@@ -64,15 +64,15 @@
 	lf := C.CString(ffmpegLog)
 	defer C.free(unsafe.Pointer(lf))
 
-	f := C.wrap_fn_create2(lf)
+	f := C.wrap_fn_create2(unsafe.Pointer(libcffmpeg), lf)
 	if f == nil {
 		return nil
 	}
 	if GB {
-		C.wrap_fn_run_gb28181(f)
+		C.wrap_fn_run_gb28181(unsafe.Pointer(libcffmpeg), f)
 	}
 	if CPU {
-		C.wrap_fn_use_cpu(f)
+		C.wrap_fn_use_cpu(unsafe.Pointer(libcffmpeg), f)
 	}
 
 	return &GoFFMPEG{
@@ -83,7 +83,7 @@
 // Free free handle
 func (h *GoFFMPEG) Free() {
 	if h.ffmpeg != nil {
-		C.wrap_fn_destroy(h.ffmpeg)
+		C.wrap_fn_destroy(unsafe.Pointer(libcffmpeg), h.ffmpeg)
 	}
 }
 
@@ -92,5 +92,10 @@
 	in := C.CString(input)
 	defer C.free(unsafe.Pointer(in))
 
-	C.wrap_fn_run(h.ffmpeg, in)
+	C.wrap_fn_run(unsafe.Pointer(libcffmpeg), h.ffmpeg, in)
+}
+
+// FPS fps
+func (h *GoFFMPEG) FPS() int {
+	return int(C.wrap_fn_fps(unsafe.Pointer(libcffmpeg), h.ffmpeg))
 }
diff --git a/gorec.go b/gorec.go
index 17bcfd8..eb44575 100644
--- a/gorec.go
+++ b/gorec.go
@@ -12,11 +12,11 @@
 func (h *GoFFMPEG) FireRecorder(sid string, id int64) {
 	csid := C.CString(sid)
 	defer C.free(unsafe.Pointer(csid))
-	C.wrap_fn_fire_recorder(h.ffmpeg, csid, C.long(id))
+	C.wrap_fn_fire_recorder(unsafe.Pointer(libcffmpeg), h.ffmpeg, csid, C.long(id))
 }
 
 // BuildRecorder build recorder
-func (h *GoFFMPEG) BuildRecorder(sid, output string, mind, maxd int, audio bool) {
+func (h *GoFFMPEG) BuildRecorder(sid, output string, id int64, mind, maxd int, audio bool) {
 	out := C.CString(output)
 	defer C.free(unsafe.Pointer(out))
 	csid := C.CString(sid)
@@ -26,7 +26,7 @@
 	if audio {
 		a = 1
 	}
-	C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd), C.int(a))
+	C.wrap_fn_recorder(unsafe.Pointer(libcffmpeg), h.ffmpeg, csid, out, C.long(id), C.int(mind), C.int(maxd), C.int(a))
 }
 
 // GetInfoRecorder info
@@ -39,7 +39,7 @@
 	var p *C.char
 	var pl C.int
 
-	C.wrap_fn_info_recorder(h.ffmpeg, &i, &id, &idl, &p, &pl)
+	C.wrap_fn_info_recorder(unsafe.Pointer(libcffmpeg), h.ffmpeg, &i, &id, &idl, &p, &pl)
 	// if p == nil {
 	// 	return -1, ""
 	// }
@@ -55,5 +55,5 @@
 
 // SetRecDurationForCache cache
 func (h *GoFFMPEG) SetRecDurationForCache(min, max int) {
-	C.wrap_fn_rec_duration(h.ffmpeg, C.int(min), C.int(max))
+	C.wrap_fn_rec_duration(unsafe.Pointer(libcffmpeg), h.ffmpeg, C.int(min), C.int(max))
 }
diff --git a/gostream.go b/gostream.go
index 6345ebd..dc94166 100644
--- a/gostream.go
+++ b/gostream.go
@@ -13,7 +13,7 @@
 	var key C.int
 	var size C.int
 
-	p := C.wrap_fn_get_avpacket(h.ffmpeg, &size, &key)
+	p := C.wrap_fn_get_avpacket(unsafe.Pointer(libcffmpeg), h.ffmpeg, &size, &key)
 	if size <= 0 {
 		return nil, 0, -1
 	}
diff --git a/libcffmpeg.c b/libcffmpeg.c
index 0486921..7c30caf 100644
--- a/libcffmpeg.c
+++ b/libcffmpeg.c
@@ -17,58 +17,9 @@
 libcffmpeg init_libcffmpeg(const char *so_file){
     libcffmpeg lib = dlopen(so_file, RTLD_LAZY);
     if(lib){
-        fn_create = (lib_cffmpeg_create)dlsym(lib, "c_ffmpeg_create");
-        release_if_err(fn_create, lib);
-        fn_create2 = (lib_cffmpeg_create)dlsym(lib, "c_ffmpeg_create2");
-        release_if_err(fn_create2, lib);
 
         fn_destroy = (lib_cffmpeg_destroy)dlsym(lib, "c_ffmpeg_destroy");
         release_if_err(fn_destroy, lib);
-
-        fn_run = (lib_cffmpeg_run)dlsym(lib, "c_ffmpeg_run");
-        release_if_err(fn_run, lib);
-        fn_gb28181 = (lib_cffmpeg_gb28181)dlsym(lib, "c_ffmpeg_run_gb28181");
-        release_if_err(fn_gb28181, lib);
-
-        fn_cpu = (lib_cffmpeg_cpu)dlsym(lib, "c_ffmepg_use_cpu");
-        release_if_err(fn_cpu, lib);
-
-        fn_rec_duration = (lib_cffmpeg_rec_duration)dlsym(lib, "c_ffmpeg_set_record_duration");
-        release_if_err(fn_rec_duration, lib);
-        fn_recorder = (lib_cffmpeg_recorder)dlsym(lib, "c_ffmpeg_build_recorder");
-        release_if_err(fn_recorder, lib);
-        fn_fire_recorder = (lib_cffmpeg_fire_recorder)dlsym(lib, "c_ffmpeg_fire_recorder");
-        release_if_err(fn_fire_recorder, lib);
-        fn_info_recorder = (lib_cffmpeg_info_recorder)dlsym(lib, "c_ffmpeg_get_info_recorder");
-        release_if_err(fn_info_recorder, lib);
-
-        fn_decoder = (lib_cffmpeg_decoder)dlsym(lib, "c_ffmpeg_build_decoder");
-        release_if_err(fn_decoder, lib);
-        fn_decoder_pic = (lib_cffmpeg_pic)dlsym(lib, "c_ffmpeg_get_pic_decoder");
-        release_if_err(fn_decoder_pic, lib);
-
-        fn_get_avpacket = (lib_cffmpeg_avpacket)dlsym(lib, "c_ffmpeg_get_avpacket");
-        release_if_err(fn_get_avpacket, lib);
-
-        fn_decode = (lib_cffmpeg_decode)dlsym(lib, "c_ffmpeg_decode");
-        release_if_err(fn_decode, lib);
-
-        fn_create_encoder = (lib_cffmpeg_create_encoder)dlsym(lib, "c_ffmpeg_create_encoder");
-        release_if_err(fn_create_encoder, lib);
-        fn_destroy_encoder = (lib_cffmpeg_destroy_encoder)dlsym(lib, "c_ffmpeg_destroy_encoder");
-        release_if_err(fn_destroy_encoder, lib);
-        fn_encode = (lib_cffmpeg_encode)dlsym(lib, "c_ffmpeg_encode");
-        release_if_err(fn_encode, lib);
-
-        fn_create_conv = (lib_cffmpeg_create_conv)dlsym(lib, "c_ffmpeg_create_conv");
-        release_if_err(fn_create_conv, lib);
-        fn_destroy_conv = (lib_cffmpeg_destroy_conv)dlsym(lib, "c_ffmpeg_destroy_conv");
-        release_if_err(fn_destroy_conv, lib);
-        fn_conv = (lib_cffmpeg_conv)dlsym(lib, "c_ffmpeg_conv");
-        release_if_err(fn_conv, lib);
-
-        fn_gpu_conv = (lib_gpu_conv)dlsym(lib, "c_gpu_conv");
-        release_if_err(fn_gpu_conv, lib);
 
     }else{
         printf("dlopen - %s\n", dlerror());  
@@ -82,77 +33,148 @@
     }
 }
 
-cffmpeg wrap_fn_create(){
+cffmpeg wrap_fn_create(void *lib){
+    if (!fn_create){
+        fn_create = (lib_cffmpeg_create)dlsym(lib, "c_ffmpeg_create");
+        release_if_err(fn_create, lib);
+    }
+
     return fn_create();
 }
 
-cffmpeg wrap_fn_create2(const char *logfile){
+cffmpeg wrap_fn_create2(void *lib, const char *logfile){
+    if (!fn_create2){
+        fn_create2 = (lib_cffmpeg_create)dlsym(lib, "c_ffmpeg_create2");
+        release_if_err(fn_create2, lib);
+    }
     return fn_create2(logfile);
 }
 
-void wrap_fn_destroy(const cffmpeg h){
+void wrap_fn_destroy(void *lib, const cffmpeg h){
     fn_destroy(h);
 }
 
-void wrap_fn_run(const cffmpeg h, const char* input){
+void wrap_fn_run(void *lib, const cffmpeg h, const char* input){
+    if (!fn_run){
+        fn_run = (lib_cffmpeg_run)dlsym(lib, "c_ffmpeg_run");
+        if (!fn_run) return;
+    }
+
     fn_run(h, input);
 }
 
-void wrap_fn_run_gb28181(const cffmpeg h){
+int wrap_fn_fps(void *lib, const cffmpeg h){
+    if(!fn_fps){
+        fn_fps = (lib_cffmpeg_fps)dlsym(lib, "c_ffmpeg_get_fps");
+        if (!fn_fps) return 25;
+    }
+    return fn_fps(h);
+}
+
+void wrap_fn_run_gb28181(void *lib, const cffmpeg h){
+    if (!fn_gb28181){
+        fn_gb28181 = (lib_cffmpeg_gb28181)dlsym(lib, "c_ffmpeg_run_gb28181");
+        if (!fn_gb28181) return;
+    }
     fn_gb28181(h);
 }
 
-void wrap_fn_use_cpu(const cffmpeg h){
+void wrap_fn_use_cpu(void *lib, const cffmpeg h){
+    if (!fn_cpu){
+        fn_cpu = (lib_cffmpeg_cpu)dlsym(lib, "c_ffmepg_use_cpu");
+        if (!fn_cpu) return;
+    }
     fn_cpu(h);
 }
 
-void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd, int audio){
-    fn_recorder(h, id, dir, mind, maxd, audio);
+void wrap_fn_recorder(void *lib, const cffmpeg h, const char* id, const char* dir, const int64_t fid, int mind, int maxd, int audio){
+    if (!fn_recorder){
+        fn_recorder = (lib_cffmpeg_recorder)dlsym(lib, "c_ffmpeg_build_recorder");
+        if (!fn_recorder) return;
+    }
+    fn_recorder(h, id, dir, fid, mind, maxd, audio);
 }
 
-void wrap_fn_rec_duration(const cffmpeg h, const int min, const int max){
+void wrap_fn_rec_duration(void *lib, const cffmpeg h, const int min, const int max){
+    if (!fn_rec_duration){
+        fn_rec_duration = (lib_cffmpeg_rec_duration)dlsym(lib, "c_ffmpeg_set_record_duration");
+        if (!fn_rec_duration) return;
+    }
     fn_rec_duration(h, min, max);
 }
 
-void wrap_fn_fire_recorder(const cffmpeg h, const char* sid, const int64_t id){
+void wrap_fn_fire_recorder(void *lib, const cffmpeg h, const char* sid, const int64_t id){
+    if (!fn_fire_recorder){
+        fn_fire_recorder = (lib_cffmpeg_fire_recorder)dlsym(lib, "c_ffmpeg_fire_recorder");
+        if (!fn_fire_recorder) return;
+    }
     fn_fire_recorder(h, sid, id);
 }
 
-void wrap_fn_info_recorder(const cffmpeg h, int* index, char** recid, int* recidLen, char** fpath, int* pathLen){
+void wrap_fn_info_recorder(void *lib, const cffmpeg h, int* index, char** recid, int* recidLen, char** fpath, int* pathLen){
+    if (!fn_info_recorder){
+        fn_info_recorder = (lib_cffmpeg_info_recorder)dlsym(lib, "c_ffmpeg_get_info_recorder");
+        if (!fn_info_recorder) return;
+    }
     return fn_info_recorder(h, index, recid, recidLen, fpath, pathLen);
 }
 
-void wrap_fn_decoder(const cffmpeg h){
+void wrap_fn_decoder(void *lib, const cffmpeg h){
+    if (!fn_decoder){
+        fn_decoder = (lib_cffmpeg_decoder)dlsym(lib, "c_ffmpeg_build_decoder");
+        if (!fn_decoder) return;
+    }
     fn_decoder(h);
 }
 
-void* wrap_fn_decoder_pic(const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id){
+void* wrap_fn_decoder_pic(void *lib, const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id){
+    if (!fn_decoder_pic){
+        fn_decoder_pic = (lib_cffmpeg_pic)dlsym(lib, "c_ffmpeg_get_pic_decoder");
+        release_if_err(fn_decoder_pic, lib);
+    }
     return fn_decoder_pic(h, wid, hei, format, length, id);
 }
 
-void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key){
+void* wrap_fn_get_avpacket(void *lib, const cffmpeg h, int* size, int* key){
+    if(!fn_get_avpacket){
+        fn_get_avpacket = (lib_cffmpeg_avpacket)dlsym(lib, "c_ffmpeg_get_avpacket");
+        release_if_err(fn_get_avpacket, lib);
+    }
     return fn_get_avpacket(h, size, key);
 }
 
 // return val: -1 open error; -2, find stream error; -3, converter create error
-void* wrap_fn_decode(const char* file, const int gb, int* wid, int* hei){
+void* wrap_fn_decode(void *lib, const char* file, const int gb, int* wid, int* hei){
+    if (!fn_decode){
+        fn_decode = (lib_cffmpeg_decode)dlsym(lib, "c_ffmpeg_decode");
+        release_if_err(fn_decode, lib);
+    }
     return fn_decode(file, gb, wid, hei);
 }
 
-void* wran_fn_gpu_conv(void *in, const int w, const int h, const int dst_w, const int dst_h, int *length){
-    return fn_gpu_conv(in, w, h, dst_w, dst_h, length);
-}
-
 // for encoder
-cencoder wrap_fn_create_encoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi){
+cencoder wrap_fn_create_encoder(void *lib, const int w, const int h, const int fps, const int br, const int scale_flag, const int gi){
+    if (!fn_create_encoder){
+        fn_create_encoder = (lib_cffmpeg_create_encoder)dlsym(lib, "c_ffmpeg_create_encoder");
+        release_if_err(fn_create_encoder, lib);
+    }
     return fn_create_encoder(w, h, fps, br, scale_flag, gi);
 }
 
-void wrap_fn_destroy_encoder(const cencoder h){
+void wrap_fn_destroy_encoder(void *lib, const cencoder h){
+    if (!fn_destroy_encoder){
+        fn_destroy_encoder = (lib_cffmpeg_destroy_encoder)dlsym(lib, "c_ffmpeg_destroy_encoder");
+        if(!fn_destroy_encoder) return;
+    }
     fn_destroy_encoder(h);
 }
 
-void* wrap_fn_encode(cencoder hdl, void *in, const int w, const int h, int *out_size, int *key){
+void* wrap_fn_encode(void *lib, cencoder hdl, void *in, const int w, const int h, int *out_size, int *key){
+    if (!fn_encode){
+        fn_encode = (lib_cffmpeg_encode)dlsym(lib, "c_ffmpeg_encode");
+        release_if_err(fn_encode, lib);
+    }
+    
     uint8_t *out = NULL;
     const int flag = fn_encode(hdl, (uint8_t*)in, w, h, &out, out_size, key);
     if (flag > 0 && out != NULL) {
@@ -164,14 +186,28 @@
 }
 
 // for conv
-cconv wrap_fn_create_conv(const int srcW, const int srcH, const int srcFormat,
+cconv wrap_fn_create_conv(void *lib, const int srcW, const int srcH, const int srcFormat,
                           const int dstW, const int dstH, const int dstFormat, const int flag){
+    if (!fn_create_conv){
+        fn_create_conv = (lib_cffmpeg_create_conv)dlsym(lib, "c_ffmpeg_create_conv");
+        release_if_err(fn_create_conv, lib);
+    }
     return fn_create_conv(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flag);
 }
 
-void wrap_fn_destroy_conv(const cconv h){
+void wrap_fn_destroy_conv(void *lib, const cconv h){
+    if (!fn_destroy_conv){
+        fn_destroy_conv = (lib_cffmpeg_destroy_conv)dlsym(lib, "c_ffmpeg_destroy_conv");
+        if(!fn_destroy_conv) return;
+    }
     fn_destroy_conv(h);
 }
-void* wrap_fn_conv(const cconv h, uint8_t *in){
+
+void* wrap_fn_conv(void *lib, const cconv h, uint8_t *in){
+    if (!fn_conv){
+        fn_conv = (lib_cffmpeg_conv)dlsym(lib, "c_ffmpeg_conv");
+        release_if_err(fn_conv, lib);
+    }
+
     return fn_conv(h, in);
 }
diff --git a/libcffmpeg.h b/libcffmpeg.h
index 231ff64..7bc4998 100644
--- a/libcffmpeg.h
+++ b/libcffmpeg.h
@@ -14,22 +14,23 @@
 typedef cffmpeg(*lib_cffmpeg_create2)(const char*);
 typedef void (*lib_cffmpeg_destroy)(const cffmpeg);
 typedef void (*lib_cffmpeg_run)(const cffmpeg, const char*);
+typedef int (*lib_cffmpeg_fps)(const cffmpeg);
 typedef void (*lib_cffmpeg_gb28181)(const cffmpeg);
 typedef void (*lib_cffmpeg_cpu)(const cffmpeg);
 typedef void (*lib_cffmpeg_rec_duration)(const cffmpeg, const int, const int);
-typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, const char*, int, int, int);
+typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, const char*, const int64_t, int, int, int);
 typedef void (*lib_cffmpeg_fire_recorder)(const cffmpeg, const char*, const int64_t);
 typedef void (*lib_cffmpeg_info_recorder)(const cffmpeg, int*, char**, int*, char**, int*);
 typedef void (*lib_cffmpeg_decoder)(const cffmpeg);
 typedef void*(*lib_cffmpeg_pic)(const cffmpeg, int*, int*, int*, int*, int64_t*);
 typedef void*(*lib_cffmpeg_avpacket)(const cffmpeg, int*, int*);
 typedef void*(*lib_cffmpeg_decode)(const char*, const int, int*, int*);
-typedef void*(*lib_gpu_conv)(void*, const int, const int, const int, const int, int *);
 
 static lib_cffmpeg_create              fn_create = NULL;
 static lib_cffmpeg_create2             fn_create2 = NULL;
 static lib_cffmpeg_destroy             fn_destroy = NULL;
 static lib_cffmpeg_run                 fn_run = NULL;
+static lib_cffmpeg_fps                 fn_fps = NULL;
 static lib_cffmpeg_gb28181             fn_gb28181 = NULL;
 static lib_cffmpeg_cpu                 fn_cpu = NULL;
 static lib_cffmpeg_rec_duration        fn_rec_duration = NULL;
@@ -40,27 +41,26 @@
 static lib_cffmpeg_pic                 fn_decoder_pic = NULL;
 static lib_cffmpeg_avpacket            fn_get_avpacket = NULL;
 static lib_cffmpeg_decode              fn_decode = NULL;
-static lib_gpu_conv                    fn_gpu_conv = NULL;
 
 typedef void* libcffmpeg;
 libcffmpeg init_libcffmpeg(const char *so_file);
 void release_libcffmpeg(libcffmpeg lib);
 
-cffmpeg wrap_fn_create();
-cffmpeg wrap_fn_create2(const char *logfile);
-void wrap_fn_destroy(const cffmpeg h);
-void wrap_fn_run(const cffmpeg h, const char* input);
-void wrap_fn_run_gb28181(const cffmpeg h);
-void wrap_fn_use_cpu(const cffmpeg h);
-void wrap_fn_rec_duration(const cffmpeg h, const int min, const int max);
-void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd, int audio);
-void wrap_fn_fire_recorder(const cffmpeg h, const char *sid, const int64_t id);
-void wrap_fn_info_recorder(const cffmpeg, int* index, char** recid, int* recidLen, char** fpath, int* pathLen);
-void wrap_fn_decoder(const cffmpeg h);
-void* wrap_fn_decoder_pic(const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id);
-void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key);
-void* wrap_fn_decode(const char* file, const int gb, int* wid, int* hei);
-void* wran_fn_gpu_conv(void *in, const int w, const int h, const int dst_w, const int dst_h, int *length);
+cffmpeg wrap_fn_create(void *lib);
+cffmpeg wrap_fn_create2(void *lib, const char *logfile);
+void wrap_fn_destroy(void *lib, const cffmpeg h);
+void wrap_fn_run(void *lib, const cffmpeg h, const char* input);
+int wrap_fn_fps(void *lib, const cffmpeg h);
+void wrap_fn_run_gb28181(void *lib, const cffmpeg h);
+void wrap_fn_use_cpu(void *lib, const cffmpeg h);
+void wrap_fn_rec_duration(void *lib, const cffmpeg h, const int min, const int max);
+void wrap_fn_recorder(void *lib, const cffmpeg h, const char* id, const char* dir, const int64_t fid, int mind, int maxd, int audio);
+void wrap_fn_fire_recorder(void *lib, const cffmpeg h, const char *sid, const int64_t id);
+void wrap_fn_info_recorder(void *lib, const cffmpeg, int* index, char** recid, int* recidLen, char** fpath, int* pathLen);
+void wrap_fn_decoder(void *lib, const cffmpeg h);
+void* wrap_fn_decoder_pic(void *lib, const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id);
+void* wrap_fn_get_avpacket(void *lib, const cffmpeg h, int* size, int* key);
+void* wrap_fn_decode(void *lib, const char* file, const int gb, int* wid, int* hei);
 // for encoder
 typedef void* cencoder;
 typedef cencoder (*lib_cffmpeg_create_encoder)(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi);
@@ -71,9 +71,9 @@
 static lib_cffmpeg_destroy_encoder fn_destroy_encoder = NULL;
 static lib_cffmpeg_encode fn_encode = NULL;
 
-cencoder wrap_fn_create_encoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi);
-void wrap_fn_destroy_encoder(const cencoder h);
-void* wrap_fn_encode(cencoder hdl, void *in, const int w, const int h, int *out_size, int *key);
+cencoder wrap_fn_create_encoder(void *lib, const int w, const int h, const int fps, const int br, const int scale_flag, const int gi);
+void wrap_fn_destroy_encoder(void *lib, const cencoder h);
+void* wrap_fn_encode(void *lib, cencoder hdl, void *in, const int w, const int h, int *out_size, int *key);
 
 
 // for conv
@@ -86,10 +86,10 @@
 static lib_cffmpeg_destroy_conv fn_destroy_conv = NULL;
 static lib_cffmpeg_conv fn_conv = NULL;
 
-cconv wrap_fn_create_conv(const int srcW, const int srcH, const int srcFormat,
+cconv wrap_fn_create_conv(void *lib, const int srcW, const int srcH, const int srcFormat,
                           const int dstW, const int dstH, const int dstFormat, const int flag);
-void wrap_fn_destroy_conv(const cconv h);
-void* wrap_fn_conv(const cconv h, uint8_t *in);
+void wrap_fn_destroy_conv(void *lib, const cconv h);
+void* wrap_fn_conv(void *lib, const cconv h, uint8_t *in);
 
 #ifdef __cplusplus
 }

--
Gitblit v1.8.0