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