video analysis2.0拆分,ffmpeg封装go接口库
chenshijun
2019-07-29 d2bec7c45f71a12734b359f10bda6302ecd8a657
Merge branch 'master' of ssh://192.168.1.14:29418/valib/goffmpeg
3个文件已删除
12个文件已修改
763 ■■■■■ 已修改文件
apiactive.go 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apiactivecallback.go 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apipassive.go 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cffmpeg.h 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/recorder.cpp 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/buz/recorder.hpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/cffmpeg.cpp 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/common/callback.hpp 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/format/FormatIn.cpp 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/format/FormatIn.hpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.cpp 315 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.hpp 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
goffmpeg.go 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libcffmpeg.c 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libcffmpeg.h 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apiactive.go
File was deleted
apiactivecallback.go
File was deleted
apipassive.go
File was deleted
cffmpeg.h
@@ -9,9 +9,6 @@
typedef void* cffmpeg;
typedef void(*rec_func)(char*, int);
typedef void(*dec_func)(void*,int,int);
cffmpeg c_ffmpeg_create();
void c_ffmpeg_destroy(const cffmpeg h);
void c_ffmpeg_run(const cffmpeg h, const char *input);
@@ -20,17 +17,14 @@
void c_ffmpeg_run_gb28181(const cffmpeg h);
void c_ffmepg_use_cpu(const cffmpeg h);
/////////passive api
void c_ffmpeg_build_recorder(const cffmpeg h, const char *dir, int mind, int maxd);
void c_ffmpeg_fire_recorder(const cffmpeg h, const int64_t id);
void c_ffmpeg_build_recorder(const cffmpeg h, const char*id, const char *dir, int mind, int maxd);
void c_ffmpeg_fire_recorder(const cffmpeg h, const char*sid, const int64_t id);
char* c_ffmpeg_get_info_recorder(const cffmpeg h, int *index, int *length);
char* c_ffmpeg_get_rec_id(const cffmpeg h, const char* p, int *length);
void c_ffmpeg_build_decoder(const cffmpeg h);
void* c_ffmpeg_get_pic_decoder(const cffmpeg h, int *wid, int *hei);
void* c_ffmpeg_get_avpacket(const cffmpeg h, int *size, int *key);
////////////active api
void c_ffmpeg_active_recorder(const cffmpeg h, const char *dir, int mind, int maxd, rec_func fn);
void c_ffmpeg_active_decoder(const cffmpeg h, dec_func fn);
//////test
void* c_ffmpeg_decode_jpeg(const cffmpeg h, const char *file, int *wid, int *hei);
csrc/buz/recorder.cpp
@@ -17,15 +17,15 @@
namespace cffmpeg_wrap{
    namespace buz{
        Recorder::Recorder(FormatIn *in)
        Recorder::Recorder(FormatIn *in, const std::string &id)
        :in_(in)
        ,out_(NULL)
        ,maxduration(30 * 25)
        ,minduration(10 * 25)
        ,end_frame(minduration)
        ,cur_frame(-1)
        ,thread_(nullptr)
        ,stop_recorder_(false)
        ,id_(id)
        ,id_frame_(0)
        ,file_frame_index_(-1)
        ,file_path_("")
@@ -33,13 +33,8 @@
        {}
        Recorder::~Recorder(){
            if(thread_){
                stop_recorder_.store(true);
                cv_.notify_one();
                thread_->join();
            }
            if(out_)
                delete out_;
            stop_recorder_.store(true);
            cv_.notify_one();
        }
        int Recorder::init_writer(){
@@ -59,6 +54,7 @@
        void Recorder::start_writer(){
            if (cur_frame == 0) {
                srandom(time(NULL));
                file_path_ = dir_ + "/" + std::to_string(random()) + ".mp4";
                out_->JustWriter(in_->getStream(), file_path_.c_str());
                logIt("start record %s", file_path_.c_str());
@@ -95,7 +91,10 @@
            }
            //callback to frame index and path
            if(func_rec_info_){
                func_rec_info_(file_frame_index_, file_path_);
                func_rec_info_(id_,file_frame_index_, file_path_);
                // logIt("recoder index %d, file name %s\n", file_frame_index_, file_path_.c_str());
            }else{
                // logIt("recorder has no func_rec_info");
            }
        }
@@ -144,13 +143,13 @@
                    }
                }
            }
            if (out_){
                delete out_;
                out_ = NULL;
            }
        }
        int Recorder::Run(const char* output, const int mind, const int maxd){
            if(thread_){
                logIt("recorder already run");
                return 0;
            }
            dir_ = output;
            int ret = init_writer();
@@ -168,9 +167,9 @@
            logIt("min %d max %d endcount %d", minduration, maxduration, end_frame);    
            thread_.reset(new std::thread([&]{
            std::thread([&]{
                run_thread();
            }));
            }).detach();
            return 0;
        }
@@ -222,7 +221,7 @@
        void Recorder::maybe_dump_gop(){
            //超过min/2,丢弃gop
            while (list_pkt_.size() > minduration /2) {
            while (list_pkt_.size() > maxduration) {
                list_pkt_.pop_front();
                while(!list_pkt_.empty()){
                    auto &cache = list_pkt_.front();
csrc/buz/recorder.hpp
@@ -29,7 +29,7 @@
        class Recorder{
            public:
                explicit Recorder(ffwrapper::FormatIn *in);
                Recorder(ffwrapper::FormatIn *in, const std::string &id);
                ~Recorder();
            public: 
@@ -60,14 +60,14 @@
                std::list<avpacket>     list_pkt_;
                std::unique_ptr<std::thread> thread_;
                std::atomic_bool        stop_recorder_;
                std::mutex              mutex_pkt_;
             std::condition_variable cv_;
                 std::condition_variable cv_;
                std::string             dir_;
                std::string             id_;
                int64_t                id_frame_;
                int64_t                 id_frame_;
                int                     file_frame_index_;
                std::string             file_path_;
                FUNC_REC_INFO           func_rec_info_;
csrc/cffmpeg.cpp
@@ -48,14 +48,14 @@
//////passive api
void c_ffmpeg_build_recorder(const cffmpeg h, const char *dir, int mind, int maxd){
void c_ffmpeg_build_recorder(const cffmpeg h, const char* id, const char *dir, int mind, int maxd){
    Wrapper *s = (Wrapper*)h;
    s->BuildRecorder(dir, mind, maxd);
    s->BuildRecorder(id, dir, mind, maxd);
}
void c_ffmpeg_fire_recorder(const cffmpeg h, const int64_t id){
void c_ffmpeg_fire_recorder(const cffmpeg h, const char* sid, const int64_t id){
    Wrapper *s = (Wrapper*)h;
    s->FireRecorder(id);
    s->FireRecorder(sid, id);
}
char* c_ffmpeg_get_info_recorder(const cffmpeg h, int *index, int *length){
@@ -63,16 +63,26 @@
    int i;
    std::string p;
    s->GetInfoRecorder(i, p);
    if(i < 0){
        return NULL;
    }
    // printf("cffmpeg get info : index : %d, file : %s\n", i, p.c_str());
    *index = i;
    *length = p.length();
    char *path = (char*)malloc(*length + 1);
    memcpy(path, p.c_str(), *length);
    path[*length] = '\0';
    return path;
}
char* c_ffmpeg_get_rec_id(const cffmpeg h, const char* p, int *length){
    Wrapper *s = (Wrapper*)h;
    std::string id = s->GetRecorderID(p);
    *length = id.length();
    char *i = (char*)malloc(*length+1);
    memcpy(i, id.c_str(), *length);
    i[*length] = '\0';
    return i;
}
void c_ffmpeg_build_decoder(const cffmpeg h){
@@ -93,23 +103,6 @@
    s->GetPacket(&data, size, key);
    return data;
}
/////////////////////active api
void c_ffmpeg_active_recorder(const cffmpeg h, const char *dir, int mind, int maxd,
                                    rec_func fn){
    Wrapper *s = (Wrapper*)h;
    s->ActiveRecorder(dir, mind, maxd,[fn](std::string &p, int &i){
        fn((char*)p.c_str(), i);
    });
}
void c_ffmpeg_active_decoder(const cffmpeg h, dec_func fn){
    Wrapper *s = (Wrapper*)h;
    s->ActiveDecoder([fn](void* d, int wid, int hei){
        fn(d, wid, hei);
    });
}
/////////////////////test
void* c_ffmpeg_decode_jpeg(const cffmpeg h, const char *file, int *wid, int *hei){
csrc/common/callback.hpp
@@ -4,9 +4,6 @@
#include <string>
#include <functional>
typedef std::function<void(std::string&, int&)> FUNC_REC;
typedef std::function<void(void*,int,int)> FUNC_DEC;
typedef std::function<void(int &id_frame, std::string &file_path)> FUNC_REC_INFO;
typedef std::function<void(std::string &id, int &id_frame, std::string &file_path)> FUNC_REC_INFO;
#endif /* callback_h */
csrc/ffmpeg/format/FormatIn.cpp
@@ -33,6 +33,7 @@
    ,io_ctx_(NULL)
    ,read_io_buff_(NULL)
    ,read_io_buff_size_(32768)
    ,handle_gb28181(NULL)
    {}
    FormatIn::~FormatIn()
@@ -53,6 +54,9 @@
                avcodec_close(dec_ctx_);
                dec_ctx_ = NULL;
            }
        }
        if (handle_gb28181){
            delete handle_gb28181;
        }
    }
@@ -90,9 +94,13 @@
        std::string fn = filename;
        //GB28181API gb28181(fn);
        handle_gb28181.addCamera(fn);
        if (handle_gb28181){
            delete handle_gb28181;
        }
        handle_gb28181 = new GB28181API;
        handle_gb28181->addCamera(fn);
        int ret = openWithCustomIO((void *)&handle_gb28181, handle_gb28181.readData, options);
        int ret = openWithCustomIO((void *)&handle_gb28181, handle_gb28181->readData, options);
        if(ret < 0){
            logIt("do openWithCustomIO failed:%d",ret);
        }
csrc/ffmpeg/format/FormatIn.hpp
@@ -63,7 +63,7 @@
        AVIOContext            *io_ctx_;
        uint8_t             *read_io_buff_;
        const int             read_io_buff_size_;
        GB28181API            handle_gb28181;
        GB28181API            *handle_gb28181;
    };
}
csrc/wrapper.cpp
@@ -30,7 +30,6 @@
    Wrapper::Wrapper()
    :input_url_("")
    ,recorder_(NULL)
    ,thread_(nullptr)
    ,stop_stream_(false)
    ,bridge_(NULL)
@@ -39,7 +38,7 @@
    ,scale_f_(SWS_POINT)
    ,gb_(0)
    ,cpu_(0)
    ,encoder_(nullptr)
    ,use_decoder_(false)
    {
        makeTheWorld();
    }
@@ -54,12 +53,7 @@
        if(bridge_){
            delete bridge_; bridge_ = NULL;
        }
        if(recorder_){
            delete recorder_; recorder_ = NULL;
        }
        if (encoder_){
            delete encoder_; encoder_ = NULL;
        }
    }
    void Wrapper::ScalePicture(const int w, const int h, const int flags){
@@ -99,100 +93,26 @@
                logIt("yolo can't find video stream\n");
                return nullptr;
            }
            bool flag = true;
            if(map_workers_.find(WORKER_DECODER) != map_workers_.end()){
                flag = in->openCodec(AVMEDIA_TYPE_VIDEO, NULL);
                auto dec_ctx = in->getCodecContext();
                if(bridge_)delete bridge_;
                scale_w_ = scale_w_ == 0 || scale_w_ > dec_ctx->width ? dec_ctx->width : scale_w_;
                scale_h_ = scale_h_ == 0 || scale_h_ > dec_ctx->height ? dec_ctx->height : scale_h_;
                AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24;
                bridge_ = new cvbridge(
                        dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
                        scale_w_, scale_h_, pix_fmt, scale_f_);
            }
            if (!flag){
                logIt("FormatIn openCodec Failed!");
                return nullptr;
            }
            return in;
        }
        return nullptr;
    }
    // ffwrapper::FormatIn* Wrapper::init_reader_gb28181(const char* input){
    //     VideoProp prop;
    //     prop.url_ = input;
    //     prop.rtsp_tcp_ = true;
    //     prop.gpu_acc_ = !cpu_;
    //     ffwrapper::FormatIn* in(new FormatIn(prop.gpuAccl()));
    //     AVDictionary *avdic = prop.optsFormat();
    //     int flag = in->openGb28181(input, &avdic);
    //     if(avdic){
    //         logIt("ERROR:in->openGb28181(input, &avdic):flag:%d\n",flag);
    //         av_dict_free(&avdic);
    //     }
    //     if(flag == 0){
    //         if(!in->findStreamInfo(NULL)){
    //             logIt("yolo can't find video stream\n");
    //             return nullptr;
    //         }
    //         bool flag = true;
    //         if(map_workers_.find(WORKER_DECODER) != map_workers_.end()){
    //             flag = in->openCodec(AVMEDIA_TYPE_VIDEO, NULL);
    //             auto dec_ctx = in->getCodecContext();
    //             if(bridge_)delete bridge_;
    //             scale_w_ = scale_w_ == 0 || scale_w_ > dec_ctx->width ? dec_ctx->width : scale_w_;
    //             scale_h_ = scale_h_ == 0 || scale_h_ > dec_ctx->height ? dec_ctx->height : scale_h_;
    //             AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24;
    //             bridge_ = new cvbridge(
    //                     dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
    //                     scale_w_, scale_h_, pix_fmt, scale_f_);
    //         }
    //         if (!flag){
    //             logIt("FormatIn openCodec Failed!");
    //             return nullptr;
    //         }
    //         return in;
    //     }
    //     return nullptr;
    // }
    int Wrapper::init_recorder(FormatIn *in, std::string dir, const int mind, const int maxd){
        if(!in){
            logIt("Init wrapper first");
            return -1;
        }
        if(recorder_){
            logIt("recorder exist");
            delete recorder_;
    int Wrapper::RunStream(const char* input){
        if(thread_){
            logIt("wrapper run stream already run");
            return 0;
        }
        recorder_ = new Recorder(in);
        recorder_->SetCallback([&](int &index, std::string &path){
            cache_rec_info(index, path);
        });
        input_url_ = input;
        int trycnt = 0;
        while(trycnt < 100){
            const int ret = recorder_->Run(dir.c_str(), mind, maxd);
            if(ret == 0) break;
            usleep(200000);
        }
        return trycnt == 100;
    }
        thread_.reset(new std::thread([&]{
            run_stream_thread();
        }));
    void Wrapper::init_worker(ffwrapper::FormatIn *in){
        for(auto &i : map_workers_){
            if(i.second(in) != 0){
                logIt("worker %d init error", i.first);
            }
        }
        return 0;
    }
    void Wrapper::run_stream_thread(){
@@ -205,7 +125,6 @@
                usleep(200000);
                continue;
            }
            init_worker(in.get());
            int64_t id = 0;
            avpacket pkt;
@@ -234,50 +153,107 @@
        }
    }
    int Wrapper::RunStream(const char* input){
        if(thread_){
            logIt("wrapper run stream already run");
            return 0;
        }
    void Wrapper::run_worker(ffwrapper::FormatIn *in, avpacket &pkt){
        if(!pkt.data) return;
        if (use_decoder_) {
            if(in->getCodecContext() == NULL){
                bool flag = true;
                flag = in->openCodec(AVMEDIA_TYPE_VIDEO, NULL);
                auto dec_ctx = in->getCodecContext();
                if(bridge_)delete bridge_;
        input_url_ = input;
                scale_w_ = scale_w_ == 0 || scale_w_ > dec_ctx->width ? dec_ctx->width : scale_w_;
                scale_h_ = scale_h_ == 0 || scale_h_ > dec_ctx->height ? dec_ctx->height : scale_h_;
        thread_.reset(new std::thread([&]{
            run_stream_thread();
        }));
        return 0;
    }
    //////////////recorder
    void Wrapper::BuildRecorder(const char *output, const int mindur, const int maxdur){
        std::string dir(output);
        map_workers_[WORKER_RECORDER] = [=](FormatIn *in){
            return init_recorder(in, dir, mindur, maxdur);
        };
    }
    int Wrapper::FireRecorder(const int64_t &id){
        if(recorder_){
            recorder_->FireRecorder(id);
        }
    }
    void Wrapper::cache_rec_info(int &index, std::string &path){
        if(func_rec_){ //active api
            func_rec_(path, index);
        }else{                  // passive api
            std::lock_guard<std::mutex> l(mutex_rec_);
            while(list_rec_.size() > 10){
                for(int i = 0; i < 5; i++){
                    list_rec_.pop_front();
                AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24;
                bridge_ = new cvbridge(
                        dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
                        scale_w_, scale_h_, pix_fmt, scale_f_);
                if (!flag){
                    logIt("FormatIn openCodec Failed!");
                }
            }
            struct record_file_info info;
            info.file_frame_index = index;
            info.file_path = path;
            list_rec_.emplace_back(info);
            auto frame(std::make_shared<FrameData>());
            auto ret = in->decode(frame, pkt.data);
            if(ret == 1){
                //吐出数据
                cache_pic(frame);
            }
        }
        for(auto &i : map_rec_){
            if (!i.second.rec){
                i.second.rec = i.second.fn_init(in);
            }
            if (i.second.rec){
                i.second.rec->CachePacket(pkt);
            }
        }
    }
    //////////////recorder
    std::shared_ptr<Recorder> Wrapper::init_recorder(FormatIn *in, std::string id,std::string dir, const int mind, const int maxd){
        if(!in){
            logIt("Init wrapper first");
            return nullptr;
        }
        auto rec = std::make_shared<Recorder>(in, id);
        rec->SetCallback([&](std::string &id, int &index, std::string &path){
            cache_rec_info(id, index, path);
        });
        int trycnt = 0;
        while(trycnt < 100){
            const int ret = rec->Run(dir.c_str(), mind, maxd);
            if(ret == 0) break;
            usleep(200000);
        }
        if (trycnt < 100){
            return rec;
        }
        return nullptr;
    }
    void Wrapper::BuildRecorder(const char* id, const char *output, const int mindur, const int maxdur){
        std::string rid(id);
        std::string dir(output);
        auto fn = [=](FormatIn *in){
            return init_recorder(in, rid, dir, mindur, maxdur);
        };
        std::shared_ptr<Recorder> rec(nullptr);
        FnRec r = FnRec{fn, rec};
        map_rec_[rid] = r;
    }
    int Wrapper::FireRecorder(const char* sid,const int64_t &id){
        auto iter = map_rec_.find(sid);
        if (iter != map_rec_.end()){
            if(iter->second.rec){
                iter->second.rec->FireRecorder(id);
            }
        }
    }
    void Wrapper::cache_rec_info(std::string &id, int &index, std::string &path){
        std::lock_guard<std::mutex> l(mutex_rec_);
        while(list_rec_.size() > 100){
            for(int i = 0; i < 25; i++){
                list_rec_.pop_front();
            }
        }
        struct record_file_info info;
        info.file_frame_index = index;
        info.file_path = path;
        list_rec_.emplace_back(info);
        list_rec_map_[path] = id;
        logIt("list rec files count : %d", list_rec_.size());
        map_rec_.erase(id);
    }
    void Wrapper::GetInfoRecorder(int &index, std::string &path){
@@ -291,11 +267,21 @@
        index = info.file_frame_index;
        path = info.file_path;
        list_rec_.pop_front();
        // logIt("go get info index: %d, file: %s\n", index, path.c_str());
    }
    std::string Wrapper::GetRecorderID(const std::string &path){
        std::string ret("");
        auto iter = list_rec_map_.find(path);
        if (iter != list_rec_map_.end()){
            ret = iter->second;
            list_rec_map_.erase(iter);
        }
        return ret;
    }
    ////////decoder
    void Wrapper::BuildDecoder(){
        map_workers_[WORKER_DECODER] = [&](FormatIn*){return 0;};
        use_decoder_ = true;
    }
    void Wrapper::cache_pic(std::shared_ptr<ffwrapper::FrameData> &frame){
@@ -310,9 +296,8 @@
            bridge_->copyPicture(data, frm);
            pic.data = data;
        }
        if(func_dec_){
            func_dec_(pic.data, pic.w, pic.h);
        }else{
        {
            std::lock_guard<std::mutex> l(mutex_pic_);
            while(list_pic_.size() > 10){
                for(int i = 0; i < 5; i++){
@@ -361,34 +346,6 @@
            }
        }
        list_avpkt_.emplace_back(pkt);
    }
    void Wrapper::run_worker(ffwrapper::FormatIn *in, avpacket &pkt){
        if(!pkt.data) return;
        if (map_workers_.find(WORKER_DECODER) != map_workers_.end()) {
            auto frame(std::make_shared<FrameData>());
            auto ret = in->decode(frame, pkt.data);
            if(ret == 1){
                //吐出数据
                cache_pic(frame);
            }
        }
        if(recorder_){
            recorder_->CachePacket(pkt);
        }
    }
    ///// active api
    void Wrapper::ActiveRecorder(const char *dir, const int mind, const int maxd,
                                FUNC_REC func){
        BuildRecorder(dir, mind, maxd);
        func_rec_ = func;
    }
    void Wrapper::ActiveDecoder(FUNC_DEC fn){
        BuildDecoder();
        func_dec_ = fn;
    }
    ////// test
@@ -443,36 +400,6 @@
        return NULL;
    }
    void Wrapper::BuildEncoder(const char *file, const int w, const int h, const int fps, const int br, const int gi){
        std::string dir(file);
        map_workers_[WORKER_ENCODER] = [=](FormatIn *in){
            return init_encoder(in, dir.c_str(), w, h, fps, br, gi);
        };
    }
    int Wrapper::init_encoder(FormatIn *in, const char *file, const int w, const int h, const int fps, const int br, const int gi){
        if(!in){
            logIt("Init wrapper first");
            return -1;
        }
        if(encoder_){
            logIt("recorder exist");
            delete encoder_;
        }
        VideoProp prop_;
        AVCodecContext *ctx = in->getCodecContext();
        if(w == 0 && h == 0){
            prop_.width_ = ctx->width;
            prop_.height_ = ctx->height;
        }
        prop_.sample_aspect_ratio_ = ctx->sample_aspect_ratio;
        encoder_ = new FormatOut(prop_, file);
        return 0;
    }
/////// for encoder
    typedef struct _PicEncoder{
csrc/wrapper.hpp
@@ -28,15 +28,8 @@
    class cvbridge;
}
enum WORKER{
    WORKER_RECORDER = 0,
    WORKER_DECODER,
    WORKER_ENCODER,
};
namespace cffmpeg_wrap{
    typedef std::function<int(ffwrapper::FormatIn*)> FUNC_WORKER;
    typedef struct _pic_bgr24{
        unsigned char *data;
@@ -48,6 +41,14 @@
        class Recorder;
        struct avpacket;
    }
    typedef std::function<std::shared_ptr<buz::Recorder>(ffwrapper::FormatIn*)> FN_REC;
    typedef struct _fn_rec{
        FN_REC fn_init;
        std::shared_ptr<buz::Recorder> rec;
    }FnRec;
    class Wrapper{
        public:
            Wrapper();
@@ -56,11 +57,10 @@
        private: 
            std::unique_ptr<ffwrapper::FormatIn> init_reader(const char* input);
            // ffwrapper::FormatIn* init_reader_gb28181(const char* input);
            void init_worker(ffwrapper::FormatIn *in);
            int init_recorder(ffwrapper::FormatIn *in, std::string dir, const int mind, const int maxd);
            void run_worker(ffwrapper::FormatIn *in, buz::avpacket &pkt);
            std::shared_ptr<buz::Recorder> init_recorder(ffwrapper::FormatIn *in, std::string id,std::string dir, const int mind, const int maxd);
            void cache_rec_info(int &index, std::string &path);
            void cache_rec_info(std::string &id, int &index, std::string &path);
            void cache_pic(std::shared_ptr<ffwrapper::FrameData> &frame);
            void cacheAVPacket(const AVPacket &pkt);
@@ -70,13 +70,10 @@
            void run_stream_thread();
        public: //recorder
            void BuildRecorder(const char *dir, const int mind, const int maxd);
            int FireRecorder(const int64_t &id);
            void BuildRecorder(const char* id,const char *dir, const int mind, const int maxd);
            int FireRecorder(const char* sid,const int64_t &id);
            void GetInfoRecorder(int &index, std::string &path);
            // active api
            void ActiveRecorder(const char *dir, const int mind, const int maxd,
                                FUNC_REC func);
            std::string GetRecorderID(const std::string &path);
            void ScalePicture(const int w, const int h, const int flags);
            void UseGB28181();
@@ -86,22 +83,18 @@
            void GetPicDecoder(unsigned char **data, int *w, int *h);
            void GetPacket(unsigned char **pktData, int *size, int *key);
            //active api
            void ActiveDecoder(FUNC_DEC fn);
        public:
            void BuildEncoder(const char *file, const int w, const int h, const int fps, const int br, const int gi);
            int init_encoder(ffwrapper::FormatIn *in, const char *file, const int w, const int h, const int fps, const int br, const int gi);
        private:
            std::string input_url_;
            buz::Recorder  *recorder_;
            std::unique_ptr<std::thread> thread_;
            std::atomic_bool    stop_stream_;
            ffwrapper::cvbridge *bridge_;
            std::unordered_map<int, FUNC_WORKER> map_workers_;
            bool use_decoder_;
            std::unordered_map<std::string, FnRec> map_rec_;
            //passive api
            struct record_file_info{
@@ -109,6 +102,8 @@
                std::string file_path;
            };
            std::list<struct record_file_info>  list_rec_;
            std::unordered_map<std::string, std::string> list_rec_map_;
            std::mutex mutex_rec_;
            std::list<pic_bgr24> list_pic_;
@@ -117,18 +112,12 @@
            std::list<AVPacket> list_avpkt_;
            std::mutex mutex_avpkt_;
            // active api
            FUNC_REC func_rec_;
            FUNC_DEC func_dec_;
            int scale_w_, scale_h_, scale_f_;
            int gb_, cpu_;
        //////////////////test frame to bgr24
        public:
            uint8_t *decodeJPEG(const char *file, int *w, int *h);
        private:
            ffwrapper::FormatOut *encoder_;
    };
    void *CreateEncoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi);
goffmpeg.go
@@ -126,6 +126,92 @@
    return nil, 0, 0
}
// FireRecorder fire recorder
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))
}
// BuildRecorder build recorder
func (h *GoFFMPEG) BuildRecorder(sid, output string, mind, maxd int) {
    out := C.CString(output)
    defer C.free(unsafe.Pointer(out))
    csid := C.CString(sid)
    defer C.free(unsafe.Pointer(csid))
    C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd))
}
// GetInfoRecorder info
func (h *GoFFMPEG) GetInfoRecorder() (int, string) {
    var i C.int = -1
    var l C.int
    p := C.wrap_fn_info_recorder(h.ffmpeg, &i, &l)
    // if p == nil {
    //     return -1, ""
    // }
    path := C.GoString(p)
    C.free(unsafe.Pointer(p))
    // fmt.Println("Go get info : ", path, " len: ", l)
    return int(i), path
}
func (h *GoFFMPEG) GetRecID(p string) string {
    pt := C.CString(p)
    defer C.free(unsafe.Pointer(pt))
    var i C.int
    cid := C.wrap_fn_rec_id(h.ffmpeg, pt, &i)
    id := C.GoString(cid)
    C.free(unsafe.Pointer(cid))
    return id
}
// BuildDecoder build decoder
func (h *GoFFMPEG) BuildDecoder() {
    C.wrap_fn_decoder(h.ffmpeg)
}
// GetPicDecoder get pic from decoder
func (h *GoFFMPEG) GetPicDecoder() ([]byte, int, int) {
    var width C.int
    var height C.int
    p := C.wrap_fn_decoder_pic(h.ffmpeg, &width, &height)
    if width == 0 && height == 0 {
        return nil, 0, 0
    }
    defer C.free(unsafe.Pointer(p))
    d := C.GoBytes(p, width*height*3)
    wid := int(width)
    hei := int(height)
    return d, wid, hei
}
//GetAVPacket get AVPacket
func (h *GoFFMPEG) GetAVPacket() ([]byte, int, int) {
    var key C.int
    var size C.int
    p := C.wrap_fn_get_avpacket(h.ffmpeg, &size, &key)
    if size <= 0 {
        return nil, 0, -1
    }
    defer C.free(unsafe.Pointer(p))
    d := C.GoBytes(p, size)
    s := int(size)
    k := int(key)
    return d, s, k
}
///////////////for encoder
// GoEncoder encoder
libcffmpeg.c
@@ -35,16 +35,14 @@
        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_rec_id = (lib_cffmpeg_rec_id)dlsym(lib, "c_ffmpeg_get_rec_id");
        release_if_err(fn_rec_id, 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_active_recorder = (lib_cffmpeg_active_recorder)dlsym(lib, "c_ffmpeg_active_recorder");
        release_if_err(fn_active_recorder, lib);
        fn_active_decoder = (lib_cffmpeg_active_decoder)dlsym(lib, "c_ffmpeg_active_decoder");
        release_if_err(fn_active_decoder, lib);
        fn_dec_jpeg = (lib_cffmpeg_decode_jpeg)dlsym(lib, "c_ffmpeg_decode_jpeg");
        release_if_err(fn_dec_jpeg, lib);
@@ -91,16 +89,20 @@
    fn_cpu(h);
}
void wrap_fn_recorder(const cffmpeg h, const char* dir, int mind, int maxd){
    fn_recorder(h, dir, mind, maxd);
void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd){
    fn_recorder(h, id, dir, mind, maxd);
}
void wrap_fn_fire_recorder(const cffmpeg h, const int64_t id){
    fn_fire_recorder(h, id);
void wrap_fn_fire_recorder(const cffmpeg h, const char* sid, const int64_t id){
    fn_fire_recorder(h, sid, id);
}
char* wrap_fn_info_recorder(const cffmpeg h, int* index, int* length){
    return fn_info_recorder(h, index, length);
}
char* wrap_fn_rec_id(const cffmpeg h, const char* path, int*length){
    return fn_rec_id(h, path, length);
}
void wrap_fn_decoder(const cffmpeg h){
@@ -113,14 +115,6 @@
void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key){
    return fn_get_avpacket(h, size, key);
}
void wrap_fn_active_recorder(const cffmpeg h, const char* dir, int mind, int maxd, rec_func fn){
    fn_active_recorder(h, dir, mind, maxd, fn);
}
void wrap_fn_active_decoder(const cffmpeg h, dec_func fn){
    fn_active_decoder(h, fn);
}
void* wrap_fn_decode_jpeg(const cffmpeg h, const char* file, int* wid, int* hei){
libcffmpeg.h
@@ -10,23 +10,19 @@
typedef void* cffmpeg;
typedef void(*rec_func)(char*, int);
typedef void(*dec_func)(void*,int,int);
typedef cffmpeg(*lib_cffmpeg_create)();
typedef void (*lib_cffmpeg_destroy)(const cffmpeg);
typedef void (*lib_cffmpeg_run)(const cffmpeg, const char*);
typedef void (*lib_cffmpeg_scale)(const cffmpeg, const int, const int, const int);
typedef void (*lib_cffmpeg_gb28181)(const cffmpeg);
typedef void (*lib_cffmpeg_cpu)(const cffmpeg);
typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, int, int);
typedef void (*lib_cffmpeg_fire_recorder)(const cffmpeg, const int64_t);
typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, const char*, int, int);
typedef void (*lib_cffmpeg_fire_recorder)(const cffmpeg, const char*, const int64_t);
typedef char*(*lib_cffmpeg_info_recorder)(const cffmpeg, int*, int*);
typedef char*(*lib_cffmpeg_rec_id)(const cffmpeg, const char*, int*);
typedef void (*lib_cffmpeg_decoder)(const cffmpeg);
typedef void*(*lib_cffmpeg_pic)(const cffmpeg, int*, int*);
typedef void*(*lib_cffmpeg_avpacket)(const cffmpeg, int*, int*);
typedef void (*lib_cffmpeg_active_recorder)(const cffmpeg, const char*, int, int, rec_func);
typedef void (*lib_cffmpeg_active_decoder)(const cffmpeg, dec_func);
typedef void*(*lib_cffmpeg_decode_jpeg)(const cffmpeg, const char*, int*, int*);
static lib_cffmpeg_create              fn_create = NULL;
@@ -38,11 +34,10 @@
static lib_cffmpeg_recorder            fn_recorder = NULL;
static lib_cffmpeg_fire_recorder       fn_fire_recorder = NULL;
static lib_cffmpeg_info_recorder       fn_info_recorder = NULL;
static lib_cffmpeg_rec_id              fn_rec_id = NULL;
static lib_cffmpeg_decoder             fn_decoder = NULL;
static lib_cffmpeg_pic                 fn_decoder_pic = NULL;
static lib_cffmpeg_avpacket            fn_get_avpacket = NULL;
static lib_cffmpeg_active_recorder     fn_active_recorder = NULL;
static lib_cffmpeg_active_decoder      fn_active_decoder = NULL;
static lib_cffmpeg_decode_jpeg         fn_dec_jpeg = NULL;
typedef void* libcffmpeg;
@@ -55,14 +50,13 @@
void wrap_fn_scale(const cffmpeg h, const int wid, const int hei, const int flags);
void wrap_fn_run_gb28181(const cffmpeg h);
void wrap_fn_use_cpu(const cffmpeg h);
void wrap_fn_recorder(const cffmpeg h, const char* dir, int mind, int maxd);
void wrap_fn_fire_recorder(const cffmpeg h, const int64_t id);
char* wrap_fn_info_recorder(const cffmpeg, int*, int*);
void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd);
void wrap_fn_fire_recorder(const cffmpeg h, const char *sid, const int64_t id);
char* wrap_fn_info_recorder(const cffmpeg, int* index, int* length);
char* wrap_fn_rec_id(const cffmpeg h, const char* path, int*length);
void wrap_fn_decoder(const cffmpeg h);
void* wrap_fn_decoder_pic(const cffmpeg h, int* wid, int* hei);
void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key);
void wrap_fn_active_recorder(const cffmpeg h, const char* dir, int mind, int maxd, rec_func fn);
void wrap_fn_active_decoder(const cffmpeg h, dec_func fn);
void* wrap_fn_decode_jpeg(const cffmpeg h, const char* file, int* wid, int* hei);