| | |
| | | //////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 |
| | |
| | | *wid = *hei = 0; |
| | | } |
| | | return p; |
| | | } |
| | | } |
| | | |
| | | // 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); |
| | | } |
| | |
| | | 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; |
| | |
| | | ,udp_port_x_(5000) |
| | | ,udp_port_y_(65000) |
| | | ,gpu_acc_(true) |
| | | ,gpu_index_(-1) |
| | | ,sample_aspect_ratio_(AVRational{0,1}) |
| | | {} |
| | | |
| | |
| | | int udp_port_y_; |
| | | |
| | | bool gpu_acc_; |
| | | |
| | | int gpu_index_; |
| | | |
| | | AVRational sample_aspect_ratio_; |
| | | |
| | | }; |
| | |
| | | |
| | | #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" |
| | |
| | | ,scale_w_(0) |
| | | ,scale_h_(0) |
| | | ,scale_f_(SWS_POINT) |
| | | ,encoder_(NULL) |
| | | { |
| | | makeTheWorld(); |
| | | } |
| | |
| | | } |
| | | if(recorder_){ |
| | | delete recorder_; recorder_ = NULL; |
| | | } |
| | | if (encoder_){ |
| | | delete encoder_; encoder_ = NULL; |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | return NULL; |
| | | } |
| | | } |
| | | |
| | | |
| | | 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; |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | |
| | | namespace ffwrapper{ |
| | | class FormatIn; |
| | | |
| | | class FormatOut; |
| | | |
| | | class VideoProp; |
| | | class CodedData; |
| | | class FrameData; |
| | |
| | | enum WORKER{ |
| | | WORKER_RECORDER = 0, |
| | | WORKER_DECODER, |
| | | WORKER_ENCODER, |
| | | }; |
| | | |
| | | namespace cffmpeg_wrap{ |
| | |
| | | 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_; |
| | |
| | | //////////////////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 |
| | |
| | | } |
| | | 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 |
| | | } |
| | |
| | | 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()); |
| | | } |
| | |
| | | |
| | | void* wrap_fn_decode_jpeg(const cffmpeg h, const char* file, int* wid, int* hei){ |
| | | return fn_dec_jpeg(h, file, wid, hei); |
| | | } |
| | | } |
| | | |
| | | // 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; |
| | | } |
| | |
| | | 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 |