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