From 927a49bc04984400cb9b968e41d299cc977e4988 Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期一, 16 九月 2019 12:54:33 +0800 Subject: [PATCH] update so file --- csrc/decoder.hpp | 50 ++ cffmpeg.h | 5 csrc/rec.hpp | 89 ++++ csrc/rec.cpp | 189 ++++++++++ csrc/buz/recorder.cpp | 2 csrc/wrapper.cpp | 369 +++----------------- csrc/stream.hpp | 29 + csrc/wrapper.hpp | 99 +---- goffmpeg.go | 33 - libcffmpeg.c | 14 csrc/cffmpeg.cpp | 35 - libcffmpeg.h | 11 csrc/decoder.cpp | 114 ++++++ csrc/stream.cpp | 36 ++ 14 files changed, 621 insertions(+), 454 deletions(-) diff --git a/cffmpeg.h b/cffmpeg.h index b411d0a..cad8cb7 100644 --- a/cffmpeg.h +++ b/cffmpeg.h @@ -19,15 +19,14 @@ /////////passive api 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_get_info_recorder(const cffmpeg h, int *index, char** recid, int *recidLen, char **fpath, int *pathLen); void c_ffmpeg_build_decoder(const cffmpeg h); void* c_ffmpeg_get_pic_decoder(const cffmpeg h, int *wid, int *hei, int64_t *id); void* c_ffmpeg_get_avpacket(const cffmpeg h, int *size, int *key); //////test -void* c_ffmpeg_decode_jpeg(const cffmpeg h, const char *file, int *wid, int *hei); +void* c_ffmpeg_decode_jpeg(const char *file, int *wid, int *hei); // pic encoder void *c_ffmpeg_create_encoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi); diff --git a/csrc/buz/recorder.cpp b/csrc/buz/recorder.cpp index 2da437c..a7086fe 100644 --- a/csrc/buz/recorder.cpp +++ b/csrc/buz/recorder.cpp @@ -124,7 +124,7 @@ //callback to frame index and path if(func_rec_info_){ - func_rec_info_(id_,file_frame_index_, file_path_); + func_rec_info_(id_, file_frame_index_, file_path_); } } diff --git a/csrc/cffmpeg.cpp b/csrc/cffmpeg.cpp index 3383b31..bb5a79f 100644 --- a/csrc/cffmpeg.cpp +++ b/csrc/cffmpeg.cpp @@ -58,31 +58,27 @@ s->FireRecorder(sid, id); } -char* c_ffmpeg_get_info_recorder(const cffmpeg h, int *index, int *length){ +void c_ffmpeg_get_info_recorder(const cffmpeg h, int *index, char** recid, int *recidLen, char **fpath, int *pathLen){ Wrapper *s = (Wrapper*)h; int i; - std::string p; - s->GetInfoRecorder(i, p); + std::string p(""), id(""); + s->GetInfoRecorder(id, i, p); // 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; -} + *pathLen = p.length(); + char *path = (char*)malloc(*pathLen + 1); + memcpy(path, p.c_str(), *pathLen); + path[*pathLen] = '\0'; + *fpath = 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; + *recidLen = id.length(); + char *rid = (char*)malloc(*recidLen + 1); + memcpy(rid, id.c_str(), *recidLen); + rid[*recidLen] = '\0'; + *recid = rid; } void c_ffmpeg_build_decoder(const cffmpeg h){ @@ -105,9 +101,8 @@ } /////////////////////test -void* c_ffmpeg_decode_jpeg(const cffmpeg h, const char *file, int *wid, int *hei){ - Wrapper *s = (Wrapper*)h; - uint8_t *p = s->decodeJPEG(file, wid, hei); +void* c_ffmpeg_decode_jpeg(const char *file, int *wid, int *hei){ + uint8_t *p = DecodeJPEG(file, wid, hei); if(!p){ *wid = *hei = 0; } diff --git a/csrc/decoder.cpp b/csrc/decoder.cpp new file mode 100644 index 0000000..381642d --- /dev/null +++ b/csrc/decoder.cpp @@ -0,0 +1,114 @@ +#include "decoder.hpp" + +#include "ffmpeg/bridge/cvbridge.hpp" +#include "ffmpeg/format/FormatIn.hpp" +#include "ffmpeg/data/CodedData.hpp" +#include "ffmpeg/data/FrameData.hpp" +#include "ffmpeg/log/log.hpp" + +extern "C"{ +#include <libavformat/avformat.h> +#include <libavutil/opt.h> +#include <libswscale/swscale.h> +} + +using namespace ffwrapper; +using namespace logif; + +namespace cffmpeg_wrap +{ + decoder::decoder(ffwrapper::FormatIn *dec, const int w, const int h, const int f) + :conv_(NULL) + ,conv_w_(w) + ,conv_h_(h) + ,conv_flag_(f) + ,decRef_(dec) + {} + + decoder::~decoder(){ + if (conv_){ + delete conv_; + } + + std::lock_guard<std::mutex> l(mutex_pic_); + for(auto &i : list_pic_){ + free(i.data); + } + list_pic_.clear(); + } + + int decoder::initDecoder(){ + if (!decRef_) return -1; + + if(decRef_->getCodecContext() == NULL){ + + bool flag = true; + flag = decRef_->openCodec(AVMEDIA_TYPE_VIDEO, NULL); + auto dec_ctx = decRef_->getCodecContext(); + if(conv_){ + delete conv_; + conv_ = NULL; + } + conv_w_ = conv_w_ == 0 || conv_w_ > dec_ctx->width ? dec_ctx->width : conv_w_; + conv_h_ = conv_h_ == 0 || conv_h_ > dec_ctx->height ? dec_ctx->height : conv_h_; + AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24; + conv_ = new cvbridge( + dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, + conv_w_, conv_h_, pix_fmt, conv_flag_); + + if (!flag){ + logIt("FormatIn openCodec Failed!"); + return -1; + } + } + return 0; + } + + int decoder::SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ + if (!data) return -1; + + if (!conv_){ + initDecoder(); + } + auto frame(std::make_shared<FrameData>()); + auto ret = decRef_->decode(frame, data); + if(ret == 1){ + //缂撳瓨鏁版嵁 + BGR24 pic; + AVFrame *frm = frame->getAVFrame(); + pic.w = conv_w_; + pic.h = conv_h_; + unsigned char *picData = (unsigned char*)malloc(pic.w * pic.h * 3); + conv_->copyPicture(picData, frm); + pic.data = picData; + pic.id = id; + + std::lock_guard<std::mutex> l(mutex_pic_); + while(list_pic_.size() > 10){ + for(int i = 0; i < 5; i++){ + auto t = list_pic_.front(); + free(t.data); + list_pic_.pop_front(); + } + } + list_pic_.emplace_back(pic); + + } + return list_pic_.size(); + } + + void decoder::GetFrame(unsigned char **data, int *w, int *h, int64_t *id){ + std::lock_guard<std::mutex> l(mutex_pic_); + if(list_pic_.empty()){ + *data = NULL; + *w = 0; + *h = 0; + return; + } + auto p = list_pic_.front(); + *data = p.data; *w = p.w; *h = p.h; + *id = p.id; + list_pic_.pop_front(); + } + +} // namespace cffmpeg_wrap diff --git a/csrc/decoder.hpp b/csrc/decoder.hpp new file mode 100644 index 0000000..0f3f76a --- /dev/null +++ b/csrc/decoder.hpp @@ -0,0 +1,50 @@ +#ifndef _cffmpeg_decoder_hpp_ +#define _cffmpeg_decoder_hpp_ + +#include <stdint.h> +#include <memory> +#include <list> +#include <mutex> + +namespace ffwrapper +{ + class FormatIn; + class cvbridge; + class CodedData; +} // namespace ffwrapper + +namespace cffmpeg_wrap +{ + typedef struct _pic_bgr24{ + unsigned char *data; + int w; + int h; + + int64_t id; + }BGR24; + + class decoder + { + private: + ffwrapper::cvbridge *conv_; + int conv_w_, conv_h_, conv_flag_; + + ffwrapper::FormatIn *decRef_; + + std::list<BGR24> list_pic_; + std::mutex mutex_pic_; + + private: + int initDecoder(); + public: + int SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); + void GetFrame(unsigned char **data, int *w, int *h, int64_t *id); + public: + decoder(ffwrapper::FormatIn *dec, const int w, const int h, const int f); + ~decoder(); + }; + +} // namespace cffmpeg_wrap + + +#endif \ No newline at end of file diff --git a/csrc/rec.cpp b/csrc/rec.cpp new file mode 100644 index 0000000..7327977 --- /dev/null +++ b/csrc/rec.cpp @@ -0,0 +1,189 @@ +#include "rec.hpp" + +#include <unistd.h> + +#include "ffmpeg/format/FormatIn.hpp" +#include "ffmpeg/data/CodedData.hpp" +#include "buz/recorder.hpp" +#include "ffmpeg/log/log.hpp" +#include "common/callback.hpp" + +using namespace logif; +using namespace ffwrapper; +using namespace cffmpeg_wrap::buz; + +namespace cffmpeg_wrap +{ + rec::rec(ffwrapper::FormatIn *in) + :recRef_(in) + ,minduration_(250) + ,maxduration_(750) + {} + + rec::~rec() + { + { + std::lock_guard<std::mutex> l(mtx_rec_); + map_rec_.clear(); + } + + { + std::lock_guard<std::mutex> l(mtx_pkt_); + list_pkt_.clear(); + } + + } + + std::unique_ptr<Recorder> rec::newRec(std::string id, std::string dir, const int mind, const int maxd){ + if(!recRef_){ + logIt("Init wrapper first"); + return nullptr; + } + + std::unique_ptr<Recorder> rec(new Recorder(recRef_, id.c_str())); + + rec->SetCallback([&](std::string &id, int &index, std::string &path){ + setRecInfo(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 rec::setRecInfo(std::string &id, int &index, std::string &path){ + + std::lock_guard<std::mutex> l(mtx_recInfo_); + while(list_recInfo_.size() > 100){ + for(int i = 0; i < 25; i++){ + list_recInfo_.pop_front(); + } + } + struct record_file_info info; + info.frmIdx = index; + info.fPath = path; + info.recID = id; + list_recInfo_.emplace_back(info); + logIt("LIST REC FILES COUNT : %d", list_recInfo_.size()); + } + + void rec::GetRecInfo(std::string &recID, int &index, std::string &path){ + + // 鑾峰彇淇℃伅 + { + std::lock_guard<std::mutex> l(mtx_recInfo_); + if(list_recInfo_.empty()){ + index = -1; + path = ""; + return; + } + auto info = list_recInfo_.front(); + recID = info.recID; + index = info.frmIdx; + path = info.fPath; + list_recInfo_.pop_front(); + } + + // 鍒犻櫎rec瀹炰緥 + { + std::lock_guard<std::mutex> l(mtx_rec_); + if (map_rec_.find(recID) != map_rec_.end()) + map_rec_.erase(recID); + + for (auto iter = map_rec_.begin(); iter != map_rec_.end();){ + if (iter->second.rec && iter->second.rec->ErrorOcurred()){ + iter == map_rec_.erase(iter); + }else{ + iter++; + } + } + } + } + + void rec::NewRec(const char* id, const char *output, const int mindur, const int maxdur){ + std::string rid(id); + std::string dir(output); + + { + std::lock_guard<std::mutex> l(mtx_rec_); + if (map_rec_.find(rid) != map_rec_.end()){ + map_rec_.erase(rid); + } + map_rec_[rid] = {rid, dir, mindur, maxdur, nullptr}; + } + + minduration_ = mindur * 25; + maxduration_ = maxdur * 25; + } + + void rec::FireRecSignal(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 rec::SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ + if (!data) return; + + cachePacket(data, id); + + std::lock_guard<std::mutex> l(mtx_rec_); + for(auto &i : map_rec_){ + if (!i.second.rec){ + i.second.rec = newRec(i.second.rid, i.second.dir, i.second.min, i.second.max); + if (i.second.rec){ + //姝ゅ嚱鏁拌繕鏈��鍑�,涓嶉渶瑕佽繖涓攣 + // std::lock_guard<std::mutex> locker(mtx_pkt_); + for(auto &k : list_pkt_){ + i.second.rec->CachePacket({k.data, k.id}); + } + // 鏂扮殑鏁版嵁缂撳瓨 + i.second.rec->CachePacket({data, id}); + logIt("START REC %d FRAMES", list_pkt_.size()); + } + }else if (i.second.rec){ + i.second.rec->CachePacket({data, id}); + } + } + } + + void rec::cachePacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ + std::lock_guard<std::mutex> l(mtx_pkt_); + //wait I + if (list_pkt_.empty()) { + AVPacket &avpkt = data->getAVPacket(); + if (!(avpkt.flags & AV_PKT_FLAG_KEY)){ + return; + } + } + list_pkt_.push_back({data, id}); + // 瓒呰繃缂撳瓨鏈�澶ч暱搴�,鍒犻櫎涓�涓猤op + shrinkCache(); + } + + int rec::shrinkCache(){ + //瓒呰繃鏈�澶х紦瀛�,涓㈠純gop + while (list_pkt_.size() > minduration_) { + list_pkt_.pop_front(); + while(!list_pkt_.empty()){ + auto &cache = list_pkt_.front(); + AVPacket &avpkt = cache.data->getAVPacket(); + if (!(avpkt.flags & AV_PKT_FLAG_KEY)){ + list_pkt_.pop_front(); + }else{ + break; + } + } + } + } +} // namespace cffmpeg_wrap diff --git a/csrc/rec.hpp b/csrc/rec.hpp new file mode 100644 index 0000000..a356ba0 --- /dev/null +++ b/csrc/rec.hpp @@ -0,0 +1,89 @@ +#ifndef _cffmpeg_rec_hpp_ +#define _cffmpeg_rec_hpp_ + +#include <string> +#include <memory> +#include <unordered_map> +#include <list> +#include <mutex> + +namespace ffwrapper +{ + class FormatIn; + class CodedData; +} // namespace ffwrapper + + +namespace cffmpeg_wrap +{ + namespace buz{ + class Recorder; + struct avpacket; + } + + + class rec + { + private: + ffwrapper::FormatIn *recRef_; + int maxduration_; + int minduration_; + + // 褰曞儚鐨勫疄渚�,瀵瑰簲浠诲姟 + typedef struct _fn_rec{ + std::string rid; //id瀵瑰簲浠诲姟id + std::string dir; + int min; + int max; + std::unique_ptr<buz::Recorder> rec; + }FnRec; + std::unordered_map<std::string, FnRec> map_rec_; + // 澶氱嚎绋嬫坊鍔犱换鍔″疄渚�,鍦ㄨ娴佺嚎绋嬩娇鐢ㄥ綍鍍�,浣嗘槸娣诲姞鍦ㄥ彟涓�涓嚎绋� + std::mutex mtx_rec_; + + // recoder灏嗗綍鍍忔枃浠剁殑淇℃伅鏀惧埌姝ゅ + typedef struct record_file_info{ + int frmIdx; + std::string fPath; + std::string recID; + }RecInfo; + std::list<RecInfo> list_recInfo_; + // 澶氱嚎绋嬪綍鍍�,鍔犻攣鑾峰彇褰曞儚鍚庣殑淇℃伅 + std::mutex mtx_recInfo_; + + // 缂撳瓨鐨勮棰戝抚,绛夊緟firerecsignal瑙﹀彂寮�濮嬪綍鍍� + typedef struct _cache_pkt{ + std::shared_ptr<ffwrapper::CodedData> data; + int64_t id; + }CPacket; + std::list<CPacket> list_pkt_; + // 澶氱嚎绋�,鐢熶骇鑰呯嚎绋媟eader push pkt,娑堣垂鑰�,褰曞儚绾跨▼pop + std::mutex mtx_pkt_; + + private: + // 鍒涘缓褰曞儚瀹炰緥 + std::unique_ptr<buz::Recorder> newRec(std::string id, std::string dir, const int mind, const int maxd); + // 褰曞儚瀹炰緥鐨勫洖璋冨嚱鏁�,褰曞儚瀹屾垚鍚庤缃綍鍍忔枃浠惰矾寰�,id鍜屽抚id + void setRecInfo(std::string &id, int &index, std::string &path); + // 缂撳瓨瑙嗛鍖� + void cachePacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); + // 涓㈠純缂撳瓨 + int shrinkCache(); + public: + void NewRec(const char* id, const char *output, const int mindur, const int maxdur); + + // 缂撳瓨褰曞儚鐨勮棰戝寘,绛夊緟瑙﹀彂褰曞儚,鎴栫洿鎺ユ斁鍒板綍鍍忕紦瀛� + void SetPacket(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); + // 瑙﹀彂褰曞儚 + void FireRecSignal(const char* sid,const int64_t &id); + // 鑾峰彇褰曞儚鏂囦欢璺緞鍜屽抚id + void GetRecInfo(std::string &recID, int &index, std::string &path); + + public: + explicit rec(ffwrapper::FormatIn *in); + ~rec(); + }; +} // namespace cffmpeg_wrap + + +#endif \ No newline at end of file diff --git a/csrc/stream.cpp b/csrc/stream.cpp new file mode 100644 index 0000000..42b8d73 --- /dev/null +++ b/csrc/stream.cpp @@ -0,0 +1,36 @@ +#include "stream.hpp" + +#include "ffmpeg/data/CodedData.hpp" + +namespace cffmpeg_wrap{ + stream::stream(){ + + } + stream::~stream(){ + + } + + int stream::SetPacket(std::shared_ptr<ffwrapper::CodedData> data){ + if (data){ + std::lock_guard<std::mutex> locker(mutex_avpkt_); + list_avpkt_.push_back(data); + return list_avpkt_.size(); + } + return 0; + } + + void stream::GetPacket(unsigned char **pktData, int *size, int *key){ + std::lock_guard<std::mutex> l(mutex_avpkt_); + if(list_avpkt_.empty()){ + return; + } + auto data = list_avpkt_.front(); + auto pkt = data->getAVPacket(); + *key = pkt.flags & AV_PKT_FLAG_KEY; + *size = pkt.size; + *pktData = (unsigned char *)malloc(*size); + memcpy(*pktData, pkt.data, pkt.size); + + list_avpkt_.pop_front(); + } +} \ No newline at end of file diff --git a/csrc/stream.hpp b/csrc/stream.hpp new file mode 100644 index 0000000..5cbc44a --- /dev/null +++ b/csrc/stream.hpp @@ -0,0 +1,29 @@ +#ifndef _cffmpeg_stream_hpp_ +#define _cffmpeg_stream_hpp_ + +#include <list> +#include <mutex> +#include <memory> + +namespace ffwrapper{ + class CodedData; +} + +namespace cffmpeg_wrap{ + class stream + { + private: + std::list<std::shared_ptr<ffwrapper::CodedData> > list_avpkt_; + std::mutex mutex_avpkt_; + + public: + stream(/* args */); + ~stream(); + + int SetPacket(std::shared_ptr<ffwrapper::CodedData> data); + void GetPacket(unsigned char **pktData, int *size, int *key); + }; + +} + +#endif \ No newline at end of file diff --git a/csrc/wrapper.cpp b/csrc/wrapper.cpp index 513055e..9fc2e25 100644 --- a/csrc/wrapper.cpp +++ b/csrc/wrapper.cpp @@ -21,8 +21,11 @@ #include "buz/recorder.hpp" -using namespace logif; +#include "stream.hpp" +#include "decoder.hpp" +#include "rec.hpp" +using namespace logif; using namespace ffwrapper; namespace cffmpeg_wrap{ @@ -30,17 +33,17 @@ Wrapper::Wrapper() :input_url_("") - ,thread_(nullptr) - ,stop_stream_(false) - ,bridge_(NULL) ,scale_w_(0) ,scale_h_(0) ,scale_f_(SWS_POINT) ,gb_(0) ,cpu_(0) ,use_decoder_(false) - ,minduration(250) - ,maxduration(750) + ,thread_(nullptr) + ,stop_stream_(false) + ,stream_(nullptr) + ,decoder_(nullptr) + ,rec_(nullptr) { makeTheWorld(); } @@ -54,23 +57,11 @@ stop_stream_.store(true); thread_->join(); } - if(bridge_){ - delete bridge_; bridge_ = NULL; - } - - map_rec_.clear(); - list_rec_pkt_.clear(); - - for(auto &i : list_pic_){ - free(i.data); - } } catch(const std::exception& e) { logIt("WRAPPER EXCEPTION: ", e.what()); } - - } void Wrapper::ScalePicture(const int w, const int h, const int flags){ @@ -132,344 +123,94 @@ return 0; } + void Wrapper::init_stream(){ + if (stream_) delete stream_; + stream_ = new stream; + } + + void Wrapper::init_decoder(ffwrapper::FormatIn *in){ + if (decoder_) delete decoder_; + decoder_ = new decoder(in, scale_w_, scale_h_,scale_f_); + } + + void Wrapper::init_rec(ffwrapper::FormatIn *in){ + if (rec_) delete rec_; + rec_ = new rec(in); + } + void Wrapper::run_stream_thread(){ while(!stop_stream_.load()){ auto in = init_reader(input_url_.c_str()); - + if (!in) { logIt("ERROR: init_reader! url: %s\n", input_url_.c_str()); usleep(200000); continue; } + init_stream(); + if (use_decoder_){ + init_decoder(in.get()); + } + init_rec(in.get()); int64_t id = 0; - avpacket pkt; while(!stop_stream_.load()){ auto data(std::make_shared<CodedData>()); if(!in->readPacket(data)){ logIt("read packet error"); - data.reset(); - data = nullptr; - pkt.id = -1; - id = 0; - }else{ - pkt.id = id++; - } - pkt.data = data; - if(data != nullptr) { - cacheAVPacket(data->getAVPacket()); - } - - run_worker(in.get(), pkt); - if(!data){ - { - std::lock_guard<std::mutex> l(mutex_rec_); - map_rec_.clear(); - } - std::lock_guard<std::mutex> locker(mtx_rec_pkt_); - list_rec_pkt_.clear(); - break; - } - //test - // if(recorder_) - // if(id % 250 == 0) - // recorder_->FireRecorder(id); + } + if (stream_) stream_->SetPacket(data); + if (use_decoder_ && decoder_) decoder_->SetFrame(data, id); + if (rec_) rec_->SetPacket(data, id); + + id++; } } } - 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_; - - 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!"); - } - } - - auto frame(std::make_shared<FrameData>()); - auto ret = in->decode(frame, pkt.data); - if(ret == 1){ - //鍚愬嚭鏁版嵁 - cache_pic(frame, pkt.id); - } - } - cache_rec_pkt(pkt); - { - std::lock_guard<std::mutex> l(mutex_rec_); - - for(auto &i : map_rec_){ - if (!i.second.rec){ - i.second.rec = std::move(init_recorder(in, i.second.rid, i.second.dir, i.second.min, i.second.max)); - if (i.second.rec){ - std::lock_guard<std::mutex> locker(mtx_rec_pkt_); - for(auto &k : list_rec_pkt_){ - avpacket p = {k.data, k.id}; - i.second.rec->CachePacket(p); - } - logIt("START REC %d FRAMES", list_rec_pkt_.size()); - } - }else if (i.second.rec){ - i.second.rec->CachePacket(pkt); - } - } - - } - } - - int Wrapper::cache_rec_pkt(const avpacket &pkt){ - - std::lock_guard<std::mutex> locker(mtx_rec_pkt_); - //wait I - if (list_rec_pkt_.empty()) { - AVPacket &avpkt = pkt.data->getAVPacket(); - if (!(avpkt.flags & AV_PKT_FLAG_KEY)){ - return -1; - } - } - maybe_dump_rec_pkt(); - recpkt k = {pkt.data, pkt.id}; - list_rec_pkt_.push_back(k); - - return 0; - } - void Wrapper::maybe_dump_rec_pkt(){ - //瓒呰繃min/2,涓㈠純gop - while (list_rec_pkt_.size() > minduration) { - list_rec_pkt_.pop_front(); - while(!list_rec_pkt_.empty()){ - auto &cache = list_rec_pkt_.front(); - AVPacket &avpkt = cache.data->getAVPacket(); - if (!(avpkt.flags & AV_PKT_FLAG_KEY)){ - list_rec_pkt_.pop_front(); - }else{ - break; - } - } - } - } - - //////////////recorder - std::unique_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; - } - - std::unique_ptr<Recorder> rec(new Recorder(in, id.c_str())); - - 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); - std::lock_guard<std::mutex> l(mutex_rec_); - - // auto fn = [=](FormatIn *in){ - // return init_recorder(in, rid, dir, mindur, maxdur); - // }; - // FnRec r = FnRec{fn, nullptr}; - if (map_rec_.find(rid) != map_rec_.end()){ - map_rec_.erase(rid); + if (rec_){ + rec_->NewRec(id, output, mindur, maxdur); } - // for (auto iter = map_rec_.begin(); iter != map_rec_.end();){ - // if (iter->second.rec && iter->second.rec->ErrorOcurred()){ - // iter == map_rec_.erase(iter); - // }else{ - // iter++; - // } - // } - FnRec fr; - fr.rid = rid; - fr.dir = dir; - fr.min = mindur; - fr.max = maxdur; - map_rec_[rid] = std::move(fr); - - minduration = mindur * 25; - maxduration = maxdur * 25; } int Wrapper::FireRecorder(const char* sid,const int64_t &id){ - std::lock_guard<std::mutex> l(mutex_rec_); - - auto iter = map_rec_.find(sid); - if (iter != map_rec_.end()){ - if(iter->second.rec){ - iter->second.rec->FireRecorder(id); - } + if (rec_){ + rec_->FireRecSignal(sid, id); } - - // for (auto iter = map_rec_.begin(); iter != map_rec_.end();){ - // if (iter->second.rec && iter->second.rec->ErrorOcurred()){ - // iter == map_rec_.erase(iter); - // }else{ - // iter++; - // } - // } } - 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(); - } + void Wrapper::GetInfoRecorder(std::string &recID, int &index, std::string &path){ + if (rec_){ + rec_->GetRecInfo(recID, index, path); } - struct record_file_info info; - info.file_frame_index = index; - info.file_path = path; - info.rec_id = id; - list_rec_.emplace_back(info); - list_rec_map_[path] = id; - logIt("LIST REC FILES COUNT : %d", list_rec_.size()); - - } - - void Wrapper::GetInfoRecorder(int &index, std::string &path){ - std::lock_guard<std::mutex> l(mutex_rec_); - if(list_rec_.empty()){ - index = -1; - path = ""; - return; - } - auto info = list_rec_.front(); - index = info.file_frame_index; - path = info.file_path; - list_rec_.pop_front(); - - if (map_rec_.find(info.rec_id) != map_rec_.end()) - map_rec_.erase(info.rec_id); - - for (auto iter = map_rec_.begin(); iter != map_rec_.end();){ - if (iter->second.rec && iter->second.rec->ErrorOcurred()){ - iter == map_rec_.erase(iter); - }else{ - iter++; - } - } - - // logIt("go get info index: %d, file: %s\n", index, path.c_str()); - } - - std::string Wrapper::GetRecorderID(const std::string &path){ - std::lock_guard<std::mutex> l(mutex_rec_); - - 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(){ use_decoder_ = true; } - void Wrapper::cache_pic(std::shared_ptr<ffwrapper::FrameData> &frame, int64_t &id){ - - pic_bgr24 pic; - if(bridge_){ - AVFrame *frm = frame->getAVFrame(); - pic.w = scale_w_; - pic.h = scale_h_; - - unsigned char *data = (unsigned char*)malloc(pic.w * pic.h * 3); - bridge_->copyPicture(data, frm); - pic.data = data; - pic.id = id; - } - - { - std::lock_guard<std::mutex> l(mutex_pic_); - while(list_pic_.size() > 10){ - for(int i = 0; i < 5; i++){ - auto t = list_pic_.front(); - free(t.data); - list_pic_.pop_front(); - } - } - list_pic_.emplace_back(pic); - } - - } - void Wrapper::GetPicDecoder(unsigned char **data, int *w, int *h, int64_t *id){ - std::lock_guard<std::mutex> l(mutex_pic_); - if(list_pic_.empty()){ - *data = NULL; - *w = 0; - *h = 0; - return; + if (decoder_){ + decoder_->GetFrame(data, w, h, id); } - auto p = list_pic_.front(); - *data = p.data; *w = p.w; *h = p.h; - *id = p.id; - list_pic_.pop_front(); } void Wrapper::GetPacket(unsigned char **pktData, int *size, int *key){ - std::lock_guard<std::mutex> l(mutex_avpkt_); - if(list_avpkt_.empty()){ - return; + if (stream_){ + stream_->GetPacket(pktData, size, key); } - auto pkt = list_avpkt_.front(); - *key = pkt.flags & AV_PKT_FLAG_KEY; - *size = pkt.size; - *pktData = (unsigned char *)malloc(*size); - memcpy(*pktData, pkt.data, pkt.size); - - list_avpkt_.pop_front(); - } - void Wrapper::cacheAVPacket(const AVPacket &pkt){ - std::lock_guard<std::mutex> l(mutex_avpkt_); - while(list_avpkt_.size() > 10){ -// printf("cacheAVPacket drop packets!!!!!!!!!!\n"); - for(int i = 0; i < 5; i++){ - list_avpkt_.pop_front(); - } - } - list_avpkt_.emplace_back(pkt); } - ////// test - uint8_t *Wrapper::decodeJPEG(const char *file, int *w, int *h){ +} // end class wrapper +/////////////////////////////////////////////////////////// +///single decode or encoder + ////// decoder +namespace cffmpeg_wrap{ // start test functions + uint8_t* DecodeJPEG(const char *file, int *w, int *h){ VideoProp prop; prop.url_ = file; prop.gpu_acc_ = false; @@ -498,7 +239,7 @@ return NULL; } }else{ - logIt("open %s error", input_url_.c_str()); + logIt("open %s error", file); return NULL; } @@ -519,8 +260,6 @@ } return NULL; } - - /////// for encoder typedef struct _PicEncoder{ FormatOut *enc; diff --git a/csrc/wrapper.hpp b/csrc/wrapper.hpp index 66f2aca..d398ed4 100644 --- a/csrc/wrapper.hpp +++ b/csrc/wrapper.hpp @@ -19,40 +19,16 @@ namespace ffwrapper{ class FormatIn; - class FormatOut; class VideoProp; class CodedData; - class FrameData; - - class cvbridge; } namespace cffmpeg_wrap{ - - typedef struct _pic_bgr24{ - unsigned char *data; - int w; - int h; - - int64_t id; - }pic_bgr24; - - namespace buz{ - class Recorder; - struct avpacket; - } - - // typedef std::function<std::shared_ptr<buz::Recorder>(ffwrapper::FormatIn*)> FN_REC; - - typedef struct _fn_rec{ - std::string rid; - std::string dir; - int min; - int max; - std::unique_ptr<buz::Recorder> rec; - }FnRec; + class stream; + class decoder; + class rec; class Wrapper{ public: @@ -61,14 +37,10 @@ private: std::unique_ptr<ffwrapper::FormatIn> init_reader(const char* input); - // ffwrapper::FormatIn* init_reader_gb28181(const char* input); - void run_worker(ffwrapper::FormatIn *in, buz::avpacket &pkt); - std::unique_ptr<buz::Recorder> init_recorder(ffwrapper::FormatIn *in, std::string id,std::string dir, const int mind, const int maxd); - - void cache_rec_info(std::string &id, int &index, std::string &path); - void cache_pic(std::shared_ptr<ffwrapper::FrameData> &frame, int64_t &id); - - void cacheAVPacket(const AVPacket &pkt); + void init_stream(); + void init_decoder(ffwrapper::FormatIn *in); + void init_rec(ffwrapper::FormatIn *in); + public: int RunStream(const char* input); private: @@ -77,8 +49,7 @@ public: //recorder 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); - std::string GetRecorderID(const std::string &path); + void GetInfoRecorder(std::string &recID, int &index, std::string &path); void ScalePicture(const int w, const int h, const int flags); void UseGB28181(); @@ -87,57 +58,29 @@ void BuildDecoder(); void GetPicDecoder(unsigned char **data, int *w, int *h, int64_t *id); void GetPacket(unsigned char **pktData, int *size, int *key); - //active api private: - + // stream 鍙傛暟 std::string input_url_; + int scale_w_, scale_h_, scale_f_; + int gb_, cpu_; + bool use_decoder_; + // decoder 鍙傛暟 std::unique_ptr<std::thread> thread_; std::atomic_bool stop_stream_; - ffwrapper::cvbridge *bridge_; - - bool use_decoder_; - std::unordered_map<std::string, FnRec> map_rec_; - - //passive api - struct record_file_info{ - int file_frame_index; - std::string file_path; - std::string rec_id; - }; - 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_; - std::mutex mutex_pic_; - - std::list<AVPacket> list_avpkt_; - std::mutex mutex_avpkt_; - - int scale_w_, scale_h_, scale_f_; - int gb_, cpu_; - - typedef struct recpkt{ - std::shared_ptr<ffwrapper::CodedData> data; - int64_t id; - }recpkt; - std::list<recpkt> list_rec_pkt_; - std::mutex mtx_rec_pkt_; - int cache_rec_pkt(const buz::avpacket &pkt); - void maybe_dump_rec_pkt(); - int maxduration; - int minduration; - - //////////////////test frame to bgr24 - public: - uint8_t *decodeJPEG(const char *file, int *w, int *h); + // 涓氬姟绫� + // 鎺ㄦ祦绫� + stream* stream_; + // 瑙g爜绫� + decoder* decoder_; + // 褰曞儚绫� + rec* rec_; }; + uint8_t *DecodeJPEG(const char *file, int *w, int *h); void *CreateEncoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi); void DestroyEncoder(void *h); int Encode(void *hdl, uint8_t *in, const int w, const int h, uint8_t **out, int *size, int *key); diff --git a/goffmpeg.go b/goffmpeg.go index d79d0ba..1efcb8d 100644 --- a/goffmpeg.go +++ b/goffmpeg.go @@ -108,13 +108,13 @@ } // DecodeJPEG decode jpeg file -func (h *GoFFMPEG) DecodeJPEG(input string) ([]byte, int, int) { +func DecodeJPEG(input string) ([]byte, int, int) { in := C.CString(input) defer C.free(unsafe.Pointer(in)) var width C.int var height C.int - p := C.wrap_fn_decode_jpeg(h.ffmpeg, in, &width, &height) + p := C.wrap_fn_decode_jpeg(in, &width, &height) defer C.free(p) if width > 0 && height > 0 { @@ -144,34 +144,27 @@ } // GetInfoRecorder info -func (h *GoFFMPEG) GetInfoRecorder() (int, string) { +func (h *GoFFMPEG) GetInfoRecorder() (string, int, string) { var i C.int = -1 - var l C.int - p := C.wrap_fn_info_recorder(h.ffmpeg, &i, &l) + var id *C.char + var idl C.int + + var p *C.char + var pl C.int + + C.wrap_fn_info_recorder(h.ffmpeg, &i, &id, &idl, &p, &pl) // if p == nil { // return -1, "" // } + gID := C.GoString(id) + C.free(unsafe.Pointer(id)) path := C.GoString(p) C.free(unsafe.Pointer(p)) // fmt.Println("Go get info : ", path, " len: ", l) - return int(i), path -} - -// GetRecID get rec id -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 + return gID, int(i), path } // BuildDecoder build decoder diff --git a/libcffmpeg.c b/libcffmpeg.c index 6cb7e5a..fda4217 100644 --- a/libcffmpeg.c +++ b/libcffmpeg.c @@ -35,8 +35,6 @@ 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"); @@ -97,12 +95,8 @@ 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_info_recorder(const cffmpeg h, int* index, char** recid, int* recidLen, char** fpath, int* pathLen){ + return fn_info_recorder(h, index, recid, recidLen, fpath, pathLen); } void wrap_fn_decoder(const cffmpeg h){ @@ -117,8 +111,8 @@ return fn_get_avpacket(h, size, key); } -void* wrap_fn_decode_jpeg(const cffmpeg h, const char* file, int* wid, int* hei){ - return fn_dec_jpeg(h, file, wid, hei); +void* wrap_fn_decode_jpeg(const char* file, int* wid, int* hei){ + return fn_dec_jpeg(file, wid, hei); } // for encoder diff --git a/libcffmpeg.h b/libcffmpeg.h index cbcf14c..cf8d212 100644 --- a/libcffmpeg.h +++ b/libcffmpeg.h @@ -18,12 +18,11 @@ typedef void (*lib_cffmpeg_cpu)(const cffmpeg); 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_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*, int64_t*); typedef void*(*lib_cffmpeg_avpacket)(const cffmpeg, int*, int*); -typedef void*(*lib_cffmpeg_decode_jpeg)(const cffmpeg, const char*, int*, int*); +typedef void*(*lib_cffmpeg_decode_jpeg)(const char*, int*, int*); static lib_cffmpeg_create fn_create = NULL; static lib_cffmpeg_destroy fn_destroy = NULL; @@ -34,7 +33,6 @@ 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; @@ -52,12 +50,11 @@ void wrap_fn_use_cpu(const cffmpeg h); 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_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, int64_t *id); void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key); -void* wrap_fn_decode_jpeg(const cffmpeg h, const char* file, int* wid, int* hei); +void* wrap_fn_decode_jpeg(const char* file, int* wid, int* hei); // for encoder -- Gitblit v1.8.0