From 5e85a7e80764e1a1eae39c8ce9bafed29d8773a9 Mon Sep 17 00:00:00 2001
From: chenshijun <csj_sky@126.com>
Date: 星期二, 23 七月 2019 19:57:27 +0800
Subject: [PATCH] 增加支持推流的代码,并替换librtspclient.so

---
 csrc/ffmpeg/format/FormatIn.cpp              |    6 
 csrc/thirdparty/gb28181/lib/librtspclient.so |    0 
 apipassive.go                                |   17 +++
 csrc/wrapper.cpp                             |   29 +++++
 csrc/wrapper.hpp                             |   11 ++
 cffmpeg.h                                    |    1 
 libcffmpeg.c                                 |    6 +
 csrc/cffmpeg.cpp                             |    7 +
 libcffmpeg.h                                 |    3 
 csrc/thirdparty/gb28181/include/PsToEs.hpp   |  195 +++++++++++++++++++-------------------
 csrc/ffmpeg/format/FormatIn.hpp              |    2 
 11 files changed, 177 insertions(+), 100 deletions(-)

diff --git a/apipassive.go b/apipassive.go
index 61e67cf..84dfda5 100644
--- a/apipassive.go
+++ b/apipassive.go
@@ -55,3 +55,20 @@
 
 	return d, wid, hei
 }
+
+//GetAVPacket get AVPacket
+func (h *GoFFMPEG) GetAVPacket() ([]byte, int, int) {
+	var key C.int
+	var size C.int
+
+	p := C.wrap_fn_get_avpacket(h.ffmpeg, &size, &key)
+	if size <= 0 {
+		return nil, 0, -1
+	}
+	defer C.free(unsafe.Pointer(p))
+	d := C.GoBytes(p, size)
+	s := int(size)
+	k := int(key)
+
+	return d, s, k
+}
\ No newline at end of file
diff --git a/cffmpeg.h b/cffmpeg.h
index c7bf9d1..f992654 100644
--- a/cffmpeg.h
+++ b/cffmpeg.h
@@ -26,6 +26,7 @@
 
 void c_ffmpeg_build_decoder(const cffmpeg h);
 void* c_ffmpeg_get_pic_decoder(const cffmpeg h, int *wid, int *hei);
+void* c_ffmpeg_get_avpacket(const cffmpeg h, int *size, int *key);
 ////////////active api
 void c_ffmpeg_active_recorder(const cffmpeg h, const char *dir, int mind, int maxd, rec_func fn);
 void c_ffmpeg_active_decoder(const cffmpeg h, dec_func fn);
diff --git a/csrc/cffmpeg.cpp b/csrc/cffmpeg.cpp
index b78313e..423ef01 100644
--- a/csrc/cffmpeg.cpp
+++ b/csrc/cffmpeg.cpp
@@ -86,6 +86,13 @@
     s->GetPicDecoder(&data, wid, hei);
     return data;
 }
+
+void* c_ffmpeg_get_avpacket(const cffmpeg h, int *size, int *key){
+    Wrapper *s = (Wrapper*)h;
+    unsigned char *data = NULL;
+    s->GetPacket(&data, size, key);
+    return data;
+}
 /////////////////////active api
 void c_ffmpeg_active_recorder(const cffmpeg h, const char *dir, int mind, int maxd, 
                                     rec_func fn){
diff --git a/csrc/ffmpeg/format/FormatIn.cpp b/csrc/ffmpeg/format/FormatIn.cpp
index d61fbc7..b0a577b 100644
--- a/csrc/ffmpeg/format/FormatIn.cpp
+++ b/csrc/ffmpeg/format/FormatIn.cpp
@@ -21,7 +21,6 @@
 #include "../data/FrameData.hpp"
 
 #include "../../common/gpu/info.h"
-#include "PsToEs.hpp"
 
 using namespace logif;
 
@@ -90,9 +89,10 @@
 	int FormatIn::openGb28181(const char *filename, AVDictionary **options){
 
 	    std::string fn = filename;
-		addCamera(fn);
+		//GB28181API gb28181(fn);
+		handle_gb28181.addCamera(fn);
 
-        int ret = openWithCustomIO(NULL, readData, options);
+        int ret = openWithCustomIO((void *)&handle_gb28181, handle_gb28181.readData, options);
         if(ret < 0){
             logIt("do openWithCustomIO failed:%d",ret);
         }
diff --git a/csrc/ffmpeg/format/FormatIn.hpp b/csrc/ffmpeg/format/FormatIn.hpp
index a19d0fe..4155aae 100644
--- a/csrc/ffmpeg/format/FormatIn.hpp
+++ b/csrc/ffmpeg/format/FormatIn.hpp
@@ -3,6 +3,7 @@
 
 #include <stdint.h>
 #include <memory>
+#include "PsToEs.hpp"
 
 struct AVFormatContext;
 struct AVDictionary;
@@ -62,6 +63,7 @@
 		AVIOContext			*io_ctx_;
 		uint8_t 			*read_io_buff_;
 		const int 			read_io_buff_size_;
+		GB28181API			handle_gb28181;
 	};
 }
 
diff --git a/csrc/thirdparty/gb28181/include/PsToEs.hpp b/csrc/thirdparty/gb28181/include/PsToEs.hpp
index 663fbdb..51f613a 100644
--- a/csrc/thirdparty/gb28181/include/PsToEs.hpp
+++ b/csrc/thirdparty/gb28181/include/PsToEs.hpp
@@ -67,7 +67,6 @@
 		while (!q.empty()) q.pop_front();
 		pthread_mutex_unlock(&mtx);
     }
-
 private:
     deque<T> q;
     pthread_mutex_t mtx;
@@ -80,111 +79,115 @@
 	int buffLen;
 } frameBuffInfo;
 
-MyQueue<frameBuffInfo *> m_rtpQueue;
-long Handle;
+class GB28181API{
+public:
+	GB28181API(/*string rtspUrl*/){
+//		handle = addCamera(rtspUrl);
+	}
 
-bool pushInfo(unsigned char *data, int datalen) {
+	~GB28181API(){
+		printf("GB28181API end!\n");
+		m_rtpQueue.clearAll();
+		deleteCamera();
+	}
 
-	frameBuffInfo *info = new frameBuffInfo();
-	info->buff = new unsigned char[datalen];
-	info->buffLen = datalen;
-	memcpy(info->buff, data, datalen);
-
-	//printf(" m_rtpQueue.push befores ");
-	m_rtpQueue.push(info);
-	//printf(" m_rtpQueue.push after ");
-
-	return true;
-}
-
-int readData(void *opaque, unsigned char *buf, int bufsize) {
-
-//	GB28181API *_this = (GB28181API *)opaque;
-	int len = bufsize;
-	int diff = 0;
-	do {
-
-	//printf(" m_rtpQueue.pop before ");
-	//浠庣紦瀛樹腑鑾峰彇buffinfo
-	frameBuffInfo *buffinfo = m_rtpQueue.pop();
-//        DBG(" m_rtpQueue.pop after ");
-	diff = len - buffinfo->buffLen;
-
-	//甯ч暱澶т簬bufsize
-	if (diff < 0) {
-		printf("/甯ч暱澶т簬bufsize:%d\n", diff);
-		memcpy(buf + bufsize - len, buffinfo->buff, len);
+	bool pushInfo(unsigned char *data, int datalen) {
 
 		frameBuffInfo *info = new frameBuffInfo();
-		info->buffLen = buffinfo->buffLen - len;
-		info->buff = new unsigned char[buffinfo->buffLen - len]{};
-		memcpy(info->buff, buffinfo->buff + len, buffinfo->buffLen - len);
+		info->buff = new unsigned char[datalen];
+		info->buffLen = datalen;
+		memcpy(info->buff, data, datalen);
 
-		m_rtpQueue.push_front_one(info);
-	} else if (diff == 0) {
-		printf("/甯ч暱绛変簬bufsize:%d\n", diff);
-		memcpy(buf + bufsize - len, buffinfo->buff, buffinfo->buffLen);
-	} else if (diff > 0) {
-		printf("/甯ч暱灏忎簬bufsize:%d\n", diff);
-		memcpy(buf + bufsize - len, buffinfo->buff, buffinfo->buffLen);
-		len = len - buffinfo->buffLen;   //杩橀渶瑕佸~鍏呯殑澶у皬
-		memset(buf + bufsize - len, 0, len);
-		//涓嶇瓑寰呭~鍏咃紝鐩存帴杩涜瑙g爜
-		diff = 0;
-	}
-	delete[] buffinfo->buff;
-	delete buffinfo;
-	} while (diff > 0);
+		//printf(" m_rtpQueue.push befores ");
+		m_rtpQueue.push(info);
+		//printf(" m_rtpQueue.push after ");
 
-	return bufsize;
-}
-
-void streamCallBack(int datatype, int frametype, unsigned char *data, unsigned int datalen, long userdata)
-{
-	//GB28181API *_this = (GB28181API *)userdata;
-	printf("userdata:%ld,datatype:%d, frametype:%d,  datalen:%d\n", userdata, datatype, frametype, datalen);
-
-//	//debug===============
-//	static int count = 0;
-//	static FILE *fp_write = NULL;
-//	if(count < 100) {
-//		count++;
-//
-//		if (!fp_write) {
-//			fp_write = fopen("stream_callback.mp4", "wb+");
-//		}
-//
-//		fwrite(data, sizeof(char), datalen, fp_write);
-//	}
-//	if(count >= 100){
-//		if (!fp_write) {
-//			fclose(fp_write);
-//		}
-//	}
-//	//debug===============
-
-	static bool startFlag = false;
-	if(frametype == GB_VIDEO_FRAME_I){
-		startFlag = true;
-	}
-	if((data != NULL) && (startFlag == true)){
-		pushInfo(data, datalen);
+		return true;
 	}
 
-}
+	static int readData(void *opaque, unsigned char *buf, int bufsize) {
 
-long addCamera(string &rtsp){
-	printf("RTSPSTREAM_Open\n");
-	long userdata = 1001;
-	Handle = RTSPSTREAM_Open(rtsp.c_str(), streamCallBack, userdata);
-	return Handle;
-}
+		GB28181API *_this = (GB28181API *)opaque;
+	    int len = bufsize;
+	    int diff = 0;
+	    do {
+//			printf(" m_rtpQueue.pop before \n");
+			//浠庣紦瀛樹腑鑾峰彇buffinfo
+			frameBuffInfo *buffinfo = _this->m_rtpQueue.pop();
+//			printf(" m_rtpQueue.pop after \n");
+			diff = len - buffinfo->buffLen;
 
-void deleteCamera(void){
-	m_rtpQueue.clearAll();
-	RTSPSTREAM_Close(Handle);
-	Handle = 0;
-}
+			//甯ч暱澶т簬bufsize
+			if (diff < 0) {
+//				printf("/甯ч暱澶т簬bufsize:%d\n", diff);
+				memcpy(buf + bufsize - len, buffinfo->buff, len);
 
+				frameBuffInfo *info = new frameBuffInfo();
+				info->buffLen = buffinfo->buffLen - len;
+				info->buff = new unsigned char[buffinfo->buffLen - len]{};
+				memcpy(info->buff, buffinfo->buff + len, buffinfo->buffLen - len);
+
+//				printf("/甯ч暱澶т簬info->buffLen:%d\n", info->buffLen);
+				_this->m_rtpQueue.push_front_one(info);
+//				printf("/甯ч暱澶т簬info->buffLen\n");
+			} else if (diff == 0) {
+//				printf("/甯ч暱绛変簬bufsize:%d\n", diff);
+				memcpy(buf + bufsize - len, buffinfo->buff, buffinfo->buffLen);
+			} else if (diff > 0) {
+//				printf("/甯ч暱灏忎簬bufsize:%d\n", diff);
+				memcpy(buf + bufsize - len, buffinfo->buff, buffinfo->buffLen);
+				len = len - buffinfo->buffLen;   //杩橀渶瑕佸~鍏呯殑澶у皬
+				memset(buf + bufsize - len, 0, len);
+				//涓嶇瓑寰呭~鍏咃紝鐩存帴杩涜瑙g爜
+				diff = 0;
+			}
+			delete[] buffinfo->buff;
+			delete buffinfo;
+//			printf("/甯ч暱澶т簬info->buffLen1\n");
+	    } while (diff > 0);
+
+	    return bufsize;
+	}
+
+	static void streamCallBack(int datatype, int frametype, unsigned char *data, unsigned int datalen, long userdata)
+	{
+		GB28181API *_this = (GB28181API *)userdata;
+		//printf("userdata:%ld,datatype:%d, frametype:%d,  datalen:%d\n", userdata, datatype, frametype, datalen);
+
+		/*static FILE* fp_write = NULL;
+		if (!fp_write)
+
+		{
+
+		    fp_write = fopen("stream_callback.mp4", "wb+");
+
+		}
+
+		fwrite(data, sizeof(char), datalen, fp_write);	*/
+
+		static bool startFlag = false;
+		if(frametype == GB_VIDEO_FRAME_I){
+			startFlag = true;
+		}
+		if((data != NULL) && (startFlag == true)){
+				_this->pushInfo(data, datalen);
+		}
+	}
+
+	void addCamera(string &rtsp){
+//		long userdata = 1001;//
+		printf("RTSPSTREAM_Open\n");
+		handle = RTSPSTREAM_Open(rtsp.c_str(), streamCallBack, (long)this);
+//		return handle;
+	}
+
+	void deleteCamera(){
+		printf("RTSPSTREAM_Close\n");
+		RTSPSTREAM_Close(handle);
+	}	
+private:
+	MyQueue<frameBuffInfo *> m_rtpQueue;
+	long handle;
+};
 
 
diff --git a/csrc/thirdparty/gb28181/lib/librtspclient.so b/csrc/thirdparty/gb28181/lib/librtspclient.so
index 6757f0f..f367065 100644
--- a/csrc/thirdparty/gb28181/lib/librtspclient.so
+++ b/csrc/thirdparty/gb28181/lib/librtspclient.so
Binary files differ
diff --git a/csrc/wrapper.cpp b/csrc/wrapper.cpp
index ec891ab..06eff0e 100644
--- a/csrc/wrapper.cpp
+++ b/csrc/wrapper.cpp
@@ -218,6 +218,9 @@
                     pkt.id = id++;
                 }
                 pkt.data = data;
+                if(data != nullptr) {
+                    cacheAVPacket(data->getAVPacket());
+                }
 
                 run_worker(in.get(), pkt);
                 if(!data){
@@ -334,6 +337,30 @@
         auto p = list_pic_.front();
         *data = p.data; *w = p.w; *h = p.h;
         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;
+        }
+        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_pic_);
+        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);
     }
 
     void Wrapper::run_worker(ffwrapper::FormatIn *in, avpacket &pkt){
@@ -523,7 +550,7 @@
     	    }
     	    *size = pkt.size + extradata_size;
     	    *out = (unsigned char *)malloc(*size);
-	
+
     	    memcpy(*out, extra, extradata_size);
     	    memcpy(*out + extradata_size, pkt.data, pkt.size);
 
diff --git a/csrc/wrapper.hpp b/csrc/wrapper.hpp
index c8d928b..db45ea7 100644
--- a/csrc/wrapper.hpp
+++ b/csrc/wrapper.hpp
@@ -1,6 +1,10 @@
 #ifndef _cffmpeg_wrapper_hpp_
 #define _cffmpeg_wrapper_hpp_
 
+extern "C"{
+#include <libavcodec/avcodec.h>
+}
+
 #include <stdint.h>
 
 #include <string>
@@ -58,6 +62,8 @@
 
             void cache_rec_info(int &index, std::string &path);
             void cache_pic(std::shared_ptr<ffwrapper::FrameData> &frame);
+
+            void cacheAVPacket(const AVPacket &pkt);
         public: 
             int RunStream(const char* input);
         private: 
@@ -78,6 +84,7 @@
         public: //decoder
             void BuildDecoder();
             void GetPicDecoder(unsigned char **data, int *w, int *h);
+            void GetPacket(unsigned char **pktData, int *size, int *key);
             //active api
             void ActiveDecoder(FUNC_DEC fn);
 
@@ -106,6 +113,10 @@
 
             std::list<pic_bgr24> list_pic_;
             std::mutex mutex_pic_;
+
+            std::list<AVPacket> list_avpkt_;
+            std::mutex mutex_avpkt_;
+
             // active api
             FUNC_REC func_rec_;
             FUNC_DEC func_dec_;
diff --git a/libcffmpeg.c b/libcffmpeg.c
index bd66a10..e33a376 100644
--- a/libcffmpeg.c
+++ b/libcffmpeg.c
@@ -39,6 +39,8 @@
         release_if_err(fn_decoder, lib);
         fn_decoder_pic = (lib_cffmpeg_pic)dlsym(lib, "c_ffmpeg_get_pic_decoder");
         release_if_err(fn_decoder_pic, lib);
+        fn_get_avpacket = (lib_cffmpeg_avpacket)dlsym(lib, "c_ffmpeg_get_avpacket");
+        release_if_err(fn_get_avpacket, lib);
         fn_active_recorder = (lib_cffmpeg_active_recorder)dlsym(lib, "c_ffmpeg_active_recorder");
         release_if_err(fn_active_recorder, lib);
         fn_active_decoder = (lib_cffmpeg_active_decoder)dlsym(lib, "c_ffmpeg_active_decoder");
@@ -109,6 +111,10 @@
     return fn_decoder_pic(h, wid, hei);
 }
 
+void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key){
+    return fn_get_avpacket(h, size, key);
+}
+
 void wrap_fn_active_recorder(const cffmpeg h, const char* dir, int mind, int maxd, rec_func fn){
     fn_active_recorder(h, dir, mind, maxd, fn);
 }
diff --git a/libcffmpeg.h b/libcffmpeg.h
index d083536..1cfbaa5 100644
--- a/libcffmpeg.h
+++ b/libcffmpeg.h
@@ -24,6 +24,7 @@
 typedef char*(*lib_cffmpeg_info_recorder)(const cffmpeg, int*, int*);
 typedef void (*lib_cffmpeg_decoder)(const cffmpeg);
 typedef void*(*lib_cffmpeg_pic)(const cffmpeg, int*, int*);
+typedef void*(*lib_cffmpeg_avpacket)(const cffmpeg, int*, int*);
 typedef void (*lib_cffmpeg_active_recorder)(const cffmpeg, const char*, int, int, rec_func);
 typedef void (*lib_cffmpeg_active_decoder)(const cffmpeg, dec_func);
 typedef void*(*lib_cffmpeg_decode_jpeg)(const cffmpeg, const char*, int*, int*);
@@ -39,6 +40,7 @@
 static lib_cffmpeg_info_recorder       fn_info_recorder = NULL;
 static lib_cffmpeg_decoder             fn_decoder = NULL;
 static lib_cffmpeg_pic                 fn_decoder_pic = NULL;
+static lib_cffmpeg_avpacket            fn_get_avpacket = NULL;
 static lib_cffmpeg_active_recorder     fn_active_recorder = NULL;
 static lib_cffmpeg_active_decoder      fn_active_decoder = NULL;
 static lib_cffmpeg_decode_jpeg         fn_dec_jpeg = NULL;
@@ -58,6 +60,7 @@
 char* wrap_fn_info_recorder(const cffmpeg, int*, int*);
 void wrap_fn_decoder(const cffmpeg h);
 void* wrap_fn_decoder_pic(const cffmpeg h, int* wid, int* hei);
+void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key);
 void wrap_fn_active_recorder(const cffmpeg h, const char* dir, int mind, int maxd, rec_func fn);
 void wrap_fn_active_decoder(const cffmpeg h, dec_func fn);
 void* wrap_fn_decode_jpeg(const cffmpeg h, const char* file, int* wid, int* hei);

--
Gitblit v1.8.0