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