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