From 803388b511d31b9e25f6829298bb12e06323474c Mon Sep 17 00:00:00 2001
From: chenshijun <csj_sky@126.com>
Date: 星期三, 17 七月 2019 13:37:47 +0800
Subject: [PATCH] Merge branch 'master' of ssh://192.168.1.14:29418/valib/goffmpeg

---
 csrc/wrapper.cpp                   |  129 +++++++++++++++++++++++++
 .gitignore                         |    1 
 csrc/wrapper.hpp                   |   17 +++
 csrc/ffmpeg/format/FormatOut.cpp   |    3 
 goffmpeg.go                        |   45 +++++++++
 cffmpeg.h                          |    5 +
 csrc/ffmpeg/property/VideoProp.cpp |    1 
 csrc/ffmpeg/property/VideoProp.hpp |    3 
 libcffmpeg.c                       |   30 +++++
 csrc/cffmpeg.cpp                   |   15 ++
 libcffmpeg.h                       |   16 +++
 11 files changed, 260 insertions(+), 5 deletions(-)

diff --git a/.gitignore b/.gitignore
index d5a7476..8331c37 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@
 
 /build
 .idea
+.vscode
diff --git a/cffmpeg.h b/cffmpeg.h
index 7a09816..1eb6536 100644
--- a/cffmpeg.h
+++ b/cffmpeg.h
@@ -32,6 +32,11 @@
 //////test
 void* c_ffmpeg_decode_jpeg(const cffmpeg h, 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);
+void c_ffmpeg_destroy_encoder(void *h);
+int c_ffmpeg_encode(void *hdl, uint8_t *in, const int w, const int h, uint8_t **out, int *size, int *key);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/csrc/cffmpeg.cpp b/csrc/cffmpeg.cpp
index e083e8b..4c5ddb8 100644
--- a/csrc/cffmpeg.cpp
+++ b/csrc/cffmpeg.cpp
@@ -101,4 +101,17 @@
         *wid = *hei = 0;
     }
     return p;
-}
\ No newline at end of file
+}
+
+// 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){
+    return CreateEncoder(w, h, fps, br, scale_flag, gi);
+}
+
+void c_ffmpeg_destroy_encoder(void *h){
+    DestroyEncoder(h);
+}
+
+int c_ffmpeg_encode(void *hdl, uint8_t *in, const int w, const int h, uint8_t **out, int *size, int *key){
+    return Encode(hdl, in, w, h, out, size, key);
+}
diff --git a/csrc/ffmpeg/format/FormatOut.cpp b/csrc/ffmpeg/format/FormatOut.cpp
index 3837dbc..d319969 100644
--- a/csrc/ffmpeg/format/FormatOut.cpp
+++ b/csrc/ffmpeg/format/FormatOut.cpp
@@ -160,6 +160,9 @@
         if(prop.gpuAccl()){
             av_opt_set(enc_ctx_->priv_data, "preset", "llhp", 0);
             int idle_gpu = gpu::getGPU(120);
+            if (prop.gpu_index_ > -1){
+                idle_gpu = prop.gpu_index_;
+            }
             if(idle_gpu < 0){
                 logIt("NO GPU RESOURCE TO ENCODE");
                 return false;
diff --git a/csrc/ffmpeg/property/VideoProp.cpp b/csrc/ffmpeg/property/VideoProp.cpp
index 44ab8b2..74432d9 100644
--- a/csrc/ffmpeg/property/VideoProp.cpp
+++ b/csrc/ffmpeg/property/VideoProp.cpp
@@ -17,6 +17,7 @@
 	,udp_port_x_(5000)
 	,udp_port_y_(65000)
     ,gpu_acc_(true)
+	,gpu_index_(-1)
     ,sample_aspect_ratio_(AVRational{0,1})
 	{}
 
diff --git a/csrc/ffmpeg/property/VideoProp.hpp b/csrc/ffmpeg/property/VideoProp.hpp
index c3cbd78..a1f5561 100644
--- a/csrc/ffmpeg/property/VideoProp.hpp
+++ b/csrc/ffmpeg/property/VideoProp.hpp
@@ -39,7 +39,8 @@
 		int 			udp_port_y_;
 
 		bool 			gpu_acc_;
-        
+        int 			gpu_index_;
+		
         AVRational      sample_aspect_ratio_;
 
 	};
diff --git a/csrc/wrapper.cpp b/csrc/wrapper.cpp
index 9b4a88a..c939599 100644
--- a/csrc/wrapper.cpp
+++ b/csrc/wrapper.cpp
@@ -12,6 +12,7 @@
 
 #include "ffmpeg/configure/conf.hpp"
 #include "ffmpeg/format/FormatIn.hpp"
+#include "ffmpeg/format/FormatOut.hpp"
 #include "ffmpeg/property/VideoProp.hpp"
 #include "ffmpeg/data/CodedData.hpp"
 #include "ffmpeg/data/FrameData.hpp"
@@ -36,6 +37,7 @@
     ,scale_w_(0)
     ,scale_h_(0)
     ,scale_f_(SWS_POINT)
+    ,encoder_(NULL)
     {
         makeTheWorld();
     }
@@ -52,6 +54,9 @@
         }
         if(recorder_){
             delete recorder_; recorder_ = NULL;
+        }
+        if (encoder_){
+            delete encoder_; encoder_ = NULL;
         }
     }
 
@@ -398,4 +403,126 @@
         }
         return NULL;
     }
-}
\ No newline at end of file
+
+
+    void Wrapper::BuildEncoder(const char *file, const int w, const int h, const int fps, const int br, const int gi){
+        std::string dir(file);
+
+        map_workers_[WORKER_ENCODER] = [=](FormatIn *in){
+            return init_encoder(in, dir.c_str(), w, h, fps, br, gi);
+        };
+    }
+
+    int Wrapper::init_encoder(FormatIn *in, const char *file, const int w, const int h, const int fps, const int br, const int gi){
+        if(!in){
+            logIt("Init wrapper first");
+            return -1;
+        }
+        if(encoder_){
+            logIt("recorder exist");
+            delete encoder_;
+        }
+
+        VideoProp prop_;
+        AVCodecContext *ctx = in->getCodecContext();
+		if(w == 0 && h == 0){
+			prop_.width_ = ctx->width;
+			prop_.height_ = ctx->height;
+		}
+        prop_.sample_aspect_ratio_ = ctx->sample_aspect_ratio;
+		encoder_ = new FormatOut(prop_, file);
+
+        return 0;
+    }
+
+/////// for encoder
+    typedef struct _PicEncoder{
+        FormatOut *enc;
+        int w;
+        int h;
+        int fps;
+        int br;
+        int gi;
+        int flag;
+        cvbridge *bridge;
+    } PicEncoder;
+
+    void *CreateEncoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi){
+
+        PicEncoder *e = (PicEncoder*)malloc(sizeof(PicEncoder));
+        e->enc = NULL;
+        e->w = w;
+        e->h = h;
+        e->fps = fps;
+        e->br = br;
+        e->gi = gi;
+        e->flag = scale_flag;
+        e->bridge = NULL;
+
+        VideoProp prop_;
+        prop_.width_ = w;
+        prop_.height_ = h;
+        prop_.fps_ = fps;
+        prop_.bit_rate_ = br;
+        gi < 0 ? prop_.gpu_acc_ = false : prop_.gpu_acc_ = true;
+
+		FormatOut *enc = new FormatOut(prop_, "./88.mp4");
+        e->enc = enc;
+
+        return e;
+    }
+
+    void DestroyEncoder(void *h){
+        PicEncoder *e = (PicEncoder*)h;
+        if (e == NULL){
+            return;
+        }
+
+        delete e->bridge;
+        delete e->enc;
+
+        free(e);
+    }
+
+    int Encode(void *hdl, uint8_t *in, const int w, const int h, uint8_t **out, int *size, int *key){
+
+        PicEncoder *e = (PicEncoder*)hdl;
+        auto ctx = e->enc->getCodecContext();
+
+        if (e->bridge == NULL){
+            AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24;
+            e->bridge = new cvbridge(
+                    w, h, AV_PIX_FMT_BGR24,
+                    e->w, e->h, ctx->pix_fmt, e->flag);
+        }
+
+        AVFrame *frame = e->bridge->getAVFrame(in, w, h);
+        auto data(std::make_shared<CodedData>());
+	
+		const int flag = e->enc->encode(data, frame);
+		if(flag > 0){
+            auto pkt = data->getAVPacket();
+            int extradata_size = ctx->extradata_size;
+			uint8_t *extra = ctx->extradata;
+
+            *key = pkt.flags & AV_PKT_FLAG_KEY;
+    	    if(!(*key)){
+    	        extradata_size = 0;
+    	    }
+    	    *size = pkt.size + extradata_size;
+    	    *out = (unsigned char *)malloc(*size);
+	
+    	    memcpy(*out, extra, extradata_size);
+    	    memcpy(*out + extradata_size, pkt.data, pkt.size);
+
+		}else{
+			logIt("encode error or need more packet\n");
+		}
+
+        av_frame_free(&frame);
+
+        return flag;
+    }
+
+}
+
diff --git a/csrc/wrapper.hpp b/csrc/wrapper.hpp
index f242ee7..1145044 100644
--- a/csrc/wrapper.hpp
+++ b/csrc/wrapper.hpp
@@ -15,7 +15,8 @@
 
 namespace ffwrapper{
     class FormatIn;
-
+    class FormatOut;
+    
     class VideoProp;
     class CodedData;
     class FrameData;
@@ -26,6 +27,7 @@
 enum WORKER{
     WORKER_RECORDER = 0,
     WORKER_DECODER,
+    WORKER_ENCODER,
 };
 
 namespace cffmpeg_wrap{
@@ -76,6 +78,11 @@
             void GetPicDecoder(unsigned char **data, int *w, int *h);
             //active api
             void ActiveDecoder(FUNC_DEC fn);
+
+        public:
+            void BuildEncoder(const char *file, const int w, const int h, const int fps, const int br, const int gi);
+            int init_encoder(ffwrapper::FormatIn *in, const char *file, const int w, const int h, const int fps, const int br, const int gi);
+
         private:
 
             std::string input_url_;
@@ -105,7 +112,15 @@
         //////////////////test frame to bgr24
         public:
             uint8_t *decodeJPEG(const char *file, int *w, int *h);
+
+        private:
+            ffwrapper::FormatOut *encoder_;
     };
+
+    void *CreateEncoder(const int w, const int h, const int fps, const int br, const int scale_flag, const int gi);
+    void DestroyEncoder(void *h);
+    int Encode(void *hdl, uint8_t *in, const int w, const int h, uint8_t **out, int *size, int *key);
+
 }
 
 #endif
\ No newline at end of file
diff --git a/goffmpeg.go b/goffmpeg.go
index e33de3c..33869c0 100644
--- a/goffmpeg.go
+++ b/goffmpeg.go
@@ -113,3 +113,48 @@
 	}
 	return nil, 0, 0
 }
+
+///////////////for encoder
+
+// GoEncoder encoder
+type GoEncoder struct {
+	enc C.cencoder
+}
+
+// NewEncoder encoder
+func NewEncoder(w, h, fps, br, sFlag, gi int) *GoEncoder {
+	if w <= 0 || h <= 0 {
+		return nil
+	}
+
+	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)),
+	}
+}
+
+// Free free
+func (e *GoEncoder) Free() {
+	C.wrap_fn_destroy_encoder(e.enc)
+}
+
+// Encode pic
+func (e *GoEncoder) Encode(in []byte, w, h int) ([]byte, int, bool) {
+
+	var size C.int
+	var key C.int
+	cin := C.CBytes(in)
+	defer C.free(cin)
+
+	p := C.wrap_fn_encode(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)
+
+		isKey := false
+		if key > 0 {
+			isKey = true
+		}
+		return b, int(size), isKey
+	}
+	return nil, 0, false
+}
diff --git a/libcffmpeg.c b/libcffmpeg.c
index cb9edf7..3b3541f 100644
--- a/libcffmpeg.c
+++ b/libcffmpeg.c
@@ -41,6 +41,14 @@
         release_if_err(fn_active_decoder, lib);
         fn_dec_jpeg = (lib_cffmpeg_decode_jpeg)dlsym(lib, "c_ffmpeg_decode_jpeg");
         release_if_err(fn_dec_jpeg, lib);
+
+        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);
+
     }else{
         printf("dlopen - %s\n", dlerror());  
     }
@@ -99,4 +107,24 @@
 
 void* wrap_fn_decode_jpeg(const cffmpeg h, const char* file, int* wid, int* hei){
     return fn_dec_jpeg(h, file, wid, hei);
-}
\ No newline at end of file
+}
+
+// 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){
+    return fn_create_encoder(w, h, fps, br, scale_flag, gi);
+}
+
+void wrap_fn_destroy_encoder(const cencoder h){
+    fn_destroy_encoder(h);
+}
+
+void* wrap_fn_encode(cencoder hdl, void *in, const int w, const int h, int *out_size, int *key){
+    uint8_t *out = NULL;
+    const int flag = fn_encode(hdl, (uint8_t*)in, w, h, &out, out_size, key);
+    if (flag > 0 && out != NULL) {
+        return out;
+    }
+    *out_size = 0;
+    *key = 0;
+    return NULL;
+}
diff --git a/libcffmpeg.h b/libcffmpeg.h
index ee54ead..16cb761 100644
--- a/libcffmpeg.h
+++ b/libcffmpeg.h
@@ -56,6 +56,22 @@
 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);
 
+
+// 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);
+typedef void (*lib_cffmpeg_destroy_encoder)(cencoder h);
+typedef int (*lib_cffmpeg_encode)(cencoder hdl, uint8_t *in, const int w, const int h, uint8_t **out, int *size, int *key);
+
+static lib_cffmpeg_create_encoder fn_create_encoder = NULL;
+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);
+
 #ifdef __cplusplus
 }
 #endif

--
Gitblit v1.8.0