From 68a19a73681301c6712e10d55bc64324716dbd24 Mon Sep 17 00:00:00 2001 From: zhangmeng <775834166@qq.com> Date: 星期三, 09 十月 2019 15:38:47 +0800 Subject: [PATCH] split scale --- gostream.go | 26 + cffmpeg.h | 14 csrc/ffmpeg/configure/conf.cpp | 2 goenc.go | 54 +++ csrc/gpu-conv/CUDALERP.cu | 95 +++++ CMakeLists.txt | 8 csrc/gpu-conv/CUDALERP.h | 54 +++ csrc/wrapper.cpp | 118 ++++++ godec.go | 28 + csrc/worker/decoder.cpp | 106 ++--- csrc/wrapper.hpp | 16 goffmpeg.go | 215 ----------- csrc/worker/decoder.hpp | 24 goconv.go | 100 +++++ libcffmpeg.c | 37 + gojpeg.go | 36 ++ csrc/cffmpeg.cpp | 26 + gorec.go | 54 +++ libcffmpeg.h | 29 + 19 files changed, 725 insertions(+), 317 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ef89c8..6e1e6b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,12 @@ ${CMAKE_SOURCE_DIR}/csrc/thirdparty/whereami ${CMAKE_SOURCE_DIR}/csrc/thirdparty/ffmpeg/include ${CMAKE_SOURCE_DIR}/csrc/thirdparty/gb28181/include + ${CMAKE_SOURCE_DIR}/csrc/gpu-conv ) + +set(CUDA_TOOLKIT_ROOT_DIR /usr/local/cuda) +include_directories(/usr/local/cuda/include) +find_package(CUDA QUIET REQUIRED) link_directories(/usr/local/cuda/lib64 ${CMAKE_SOURCE_DIR}/csrc/thirdparty/gb28181/lib) @@ -47,7 +52,8 @@ file(GLOB_RECURSE FFMPEG_LIST ${CMAKE_SOURCE_DIR}/csrc/*.cpp) list(APPEND FFMPEG_LIST ${CMAKE_SOURCE_DIR}/csrc/thirdparty/whereami/whereami.c) +file(GLOB_RECURSE CUDA_LIST ${CMAKE_SOURCE_DIR}/csrc/gpu-conv/*.cu) -add_library(${BIN} SHARED ${FFMPEG_LIST}) +cuda_add_library(${BIN} SHARED ${FFMPEG_LIST} ${CUDA_LIST}) target_link_libraries(${BIN} ${LINK_LIB} numa nppig nppicc nppc -lz pthread dl rtspclient StreamParse) diff --git a/cffmpeg.h b/cffmpeg.h index c794216..ccc21a6 100644 --- a/cffmpeg.h +++ b/cffmpeg.h @@ -15,7 +15,6 @@ void c_ffmpeg_destroy(const cffmpeg h); void c_ffmpeg_run(const cffmpeg h, const char *input); -void c_ffmpeg_scale(const cffmpeg h, const int wid, const int hei, const int flags); void c_ffmpeg_run_gb28181(const cffmpeg h); void c_ffmepg_use_cpu(const cffmpeg h); /////////passive api @@ -24,10 +23,10 @@ void c_ffmpeg_get_info_recorder(const cffmpeg h, int *index, char** recid, int *recidLen, char **fpath, int *pathLen); void c_ffmpeg_build_decoder(const cffmpeg h); -void* c_ffmpeg_get_pic_decoder(const cffmpeg h, int *wid, int *hei, int64_t *id); +void* c_ffmpeg_get_pic_decoder(const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id); void* c_ffmpeg_get_avpacket(const cffmpeg h, int *size, int *key); -//////test +//////decoder void* c_ffmpeg_decode(const char *file, const int gb, int *wid, int *hei); // pic encoder @@ -35,6 +34,15 @@ 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); +// conv cpu +void *c_ffmpeg_create_conv(const int srcW, const int srcH, const int srcFormat, + const int dstW, const int dstH, const int flag); +void c_ffmpeg_destroy_conv(void *h); +void *c_ffmpeg_conv(void *h, uint8_t *in); + +// gpu conv +void* c_gpu_conv(uint8_t *in, const int w, const int h, const int dst_w, const int dst_h, int *length); + #ifdef __cplusplus } #endif diff --git a/csrc/cffmpeg.cpp b/csrc/cffmpeg.cpp index 7b31f3f..9ade6f9 100644 --- a/csrc/cffmpeg.cpp +++ b/csrc/cffmpeg.cpp @@ -33,11 +33,6 @@ s->RunStream(input); } -void c_ffmpeg_scale(const cffmpeg h, const int wid, const int hei, const int flags){ - Wrapper *s = (Wrapper*)h; - s->ScalePicture(wid, hei, flags); -} - void c_ffmpeg_run_gb28181(const cffmpeg h){ Wrapper *s = (Wrapper*)h; s->GB28181(); @@ -90,10 +85,10 @@ s->BuildDecoder(); } -void* c_ffmpeg_get_pic_decoder(const cffmpeg h, int *wid, int *hei, int64_t *id){ +void* c_ffmpeg_get_pic_decoder(const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id){ Wrapper *s = (Wrapper*)h; unsigned char *data = NULL; - s->GetPicDecoder(&data, wid, hei, id); + s->GetPicDecoder(&data, wid, hei, format, length, id); return data; } @@ -121,3 +116,20 @@ 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); } + +void *c_ffmpeg_create_conv(const int srcW, const int srcH, const int srcFormat, + const int dstW, const int dstH, const int flag){ + return CreateConvertor(srcW, srcH, srcFormat, dstW, dstH, flag); +} + +void *c_ffmpeg_conv(void *h, uint8_t *in){ + return Convert(h, in); +} + +void c_ffmpeg_destroy_conv(void *h){ + DestoryConvertor(h); +} + +void* c_gpu_conv(uint8_t *in, const int w, const int h, const int dst_w, const int dst_h, int *length){ + return ConvertYUV2BGR(in, w, h, dst_w, dst_h, length); +} \ No newline at end of file diff --git a/csrc/ffmpeg/configure/conf.cpp b/csrc/ffmpeg/configure/conf.cpp index d836840..43e45ac 100644 --- a/csrc/ffmpeg/configure/conf.cpp +++ b/csrc/ffmpeg/configure/conf.cpp @@ -13,7 +13,7 @@ av_register_all(); avfilter_register_all(); avformat_network_init(); - av_log_set_level(AV_LOG_ERROR); + av_log_set_level(AV_LOG_VERBOSE); } std::string getAVErrorDesc(const int code){ diff --git a/csrc/gpu-conv/CUDALERP.cu b/csrc/gpu-conv/CUDALERP.cu new file mode 100644 index 0000000..ee44fee --- /dev/null +++ b/csrc/gpu-conv/CUDALERP.cu @@ -0,0 +1,95 @@ +/******************************************************************* +* CUDALERP.cu +* CUDALERP +* +* Author: Kareem Omar +* kareem.omar@uah.edu +* https://github.com/komrad36 +* +* Last updated Jan 7, 2016 +*******************************************************************/ +// +// The file CUDALERP.h exposes two extremely high performance GPU +// resize operations, +// CUDALERP (bilinear interpolation), and +// CUDANERP (nearest neighbor interpolation), for 8-bit unsigned +// integer (i.e. grayscale) data. +// +// For 32-bit float data, see the CUDAFLERP project instead. +// +// CUDALERP offers superior accuracy to CUDA's built-in texture +// interpolator at comparable performance. The accuracy if compiled +// with -use-fast-math off is nearly equivalent to my CPU interpolator, +// KLERP, while still being as fast as the built-in interpolation. +// +// Particularly for large images, CUDALERP dramatically outperforms +// even the highly tuned CPU AVX2 versions. +// +// All functionality is contained in the header 'CUDALERP.h' and +// the source file 'CUDALERP.cu' and has no external dependencies at all. +// +// Note that these are intended for computer vision use(hence the speed) +// and are designed for grayscale images. +// +// The file 'main.cpp' is an example and speed test driver. +// + +#include "CUDALERP.h" + +__global__ void +#ifndef __INTELLISENSE__ +__launch_bounds__(256, 0) +#endif +CUDANERP_kernel(const cudaTextureObject_t d_img_tex, const float gxs, const float gys, uint8_t* __restrict const d_out, const int neww) { + uint32_t x = (blockIdx.x << 9) + (threadIdx.x << 1); + const uint32_t y = blockIdx.y; + const float fy = y*gys; +#pragma unroll + for (int i = 0; i < 2; ++i, ++x) { + const float fx = x*gxs; + float res = 255.0f*tex2D<float>(d_img_tex, fx, fy); + if (x < neww) d_out[y*neww + x] = res; + } +} + +__global__ void +#ifndef __INTELLISENSE__ +__launch_bounds__(256, 0) +#endif +CUDALERP_kernel(const cudaTextureObject_t d_img_tex, const float gxs, const float gys, uint8_t* __restrict const d_out, const int neww) { + uint32_t x = (blockIdx.x << 9) + (threadIdx.x << 1); + const uint32_t y = blockIdx.y; + const float fy = (y + 0.5f)*gys - 0.5f; + const float wt_y = fy - floor(fy); + const float invwt_y = 1.0f - wt_y; +#pragma unroll + for (int i = 0; i < 2; ++i, ++x) { + const float fx = (x + 0.5f)*gxs - 0.5f; + // less accurate and not really much (or any) faster + // ----------------- + // const float res = tex2D<float>(d_img_tex, fx, fy); + // ----------------- + const float4 f = tex2Dgather<float4>(d_img_tex, fx + 0.5f, fy + 0.5f); + const float wt_x = fx - floor(fx); + const float invwt_x = 1.0f - wt_x; + const float xa = invwt_x*f.w + wt_x*f.z; + const float xb = invwt_x*f.x + wt_x*f.y; + const float res = 255.0f*(invwt_y*xa + wt_y*xb) + 0.5f; + // ----------------- + if (x < neww) d_out[y*neww + x] = res; + } +} + +void CUDANERP(const cudaTextureObject_t d_img_tex, const int oldw, const int oldh, uint8_t* __restrict const d_out, const uint32_t neww, const uint32_t newh) { + const float gxs = static_cast<float>(oldw) / static_cast<float>(neww); + const float gys = static_cast<float>(oldh) / static_cast<float>(newh); + CUDANERP_kernel<<<{((neww - 1) >> 9) + 1, newh}, 256>>>(d_img_tex, gxs, gys, d_out, neww); + cudaDeviceSynchronize(); +} + +void CUDALERP(const cudaTextureObject_t d_img_tex, const int oldw, const int oldh, uint8_t* __restrict const d_out, const uint32_t neww, const uint32_t newh) { + const float gxs = static_cast<float>(oldw) / static_cast<float>(neww); + const float gys = static_cast<float>(oldh) / static_cast<float>(newh); + CUDALERP_kernel<<<{((neww - 1) >> 9) + 1, newh}, 256>>>(d_img_tex, gxs, gys, d_out, neww); + cudaDeviceSynchronize(); +} diff --git a/csrc/gpu-conv/CUDALERP.h b/csrc/gpu-conv/CUDALERP.h new file mode 100644 index 0000000..1645cb9 --- /dev/null +++ b/csrc/gpu-conv/CUDALERP.h @@ -0,0 +1,54 @@ +/******************************************************************* +* CUDALERP.h +* CUDALERP +* +* Author: Kareem Omar +* kareem.omar@uah.edu +* https://github.com/komrad36 +* +* Last updated Jan 7, 2016 +*******************************************************************/ +// +// The file CUDALERP.h exposes two extremely high performance GPU +// resize operations, +// CUDALERP (bilinear interpolation), and +// CUDANERP (nearest neighbor interpolation), for 8-bit unsigned +// integer (i.e. grayscale) data. +// +// For 32-bit float data, see the CUDAFLERP project instead. +// +// CUDALERP offers superior accuracy to CUDA's built-in texture +// interpolator at comparable performance. The accuracy if compiled +// with -use-fast-math off is nearly equivalent to my CPU interpolator, +// KLERP, while still being as fast as the built-in interpolation. +// +// Particularly for large images, CUDALERP dramatically outperforms +// even the highly tuned CPU AVX2 versions. +// +// All functionality is contained in the header 'CUDALERP.h' and +// the source file 'CUDALERP.cu' and has no external dependencies at all. +// +// Note that these are intended for computer vision use(hence the speed) +// and are designed for grayscale images. +// +// The file 'main.cpp' is an example and speed test driver. +// + +#pragma once + +#include "cuda_runtime.h" + +#include <cstdint> + +#ifdef __INTELLISENSE__ +#include <algorithm> +#define asm(x) +#include "device_launch_parameters.h" +#define __CUDACC__ +#include "device_functions.h" +#undef __CUDACC__ +#endif + +void CUDALERP(const cudaTextureObject_t d_img_tex, const int oldw, const int oldh, uint8_t* __restrict const d_out, const uint32_t neww, const uint32_t newh); + +void CUDANERP(const cudaTextureObject_t d_img_tex, const int oldw, const int oldh, uint8_t* __restrict const d_out, const uint32_t neww, const uint32_t newh); diff --git a/csrc/worker/decoder.cpp b/csrc/worker/decoder.cpp index ce5f631..67af0a1 100644 --- a/csrc/worker/decoder.cpp +++ b/csrc/worker/decoder.cpp @@ -17,27 +17,17 @@ namespace cffmpeg_wrap { - decoder::decoder(ffwrapper::FormatIn *dec, const int w, const int h, const int f) - :conv_(NULL) - ,conv_w_(w) - ,conv_h_(h) - ,conv_flag_(f) - ,decRef_(dec) + decoder::decoder(ffwrapper::FormatIn *dec) + :decRef_(dec) {} decoder::~decoder(){ - if (conv_){ - delete conv_; + std::lock_guard<std::mutex> l(mutex_frm_); + for(auto i : list_frm_){ + av_frame_free(&i.frm); } - - { - std::lock_guard<std::mutex> l(mutex_pic_); - for(auto &i : list_pic_){ - free(i.data); - } - list_pic_.clear(); - } + list_frm_.clear(); } int decoder::initDecoder(){ @@ -47,17 +37,6 @@ bool flag = true; flag = decRef_->openCodec(NULL); - auto dec_ctx = decRef_->getCodecContext(); - if(conv_){ - delete conv_; - conv_ = NULL; - } - conv_w_ = conv_w_ == 0 || conv_w_ > dec_ctx->width ? dec_ctx->width : conv_w_; - conv_h_ = conv_h_ == 0 || conv_h_ > dec_ctx->height ? dec_ctx->height : conv_h_; - AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24; - conv_ = new cvbridge( - dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, - conv_w_, conv_h_, pix_fmt, conv_flag_); if (!flag){ logIt("FormatIn openCodec Failed!"); @@ -68,25 +47,15 @@ } int decoder::saveFrame(AVFrame *frame, int64_t &id){ - //缂撳瓨鏁版嵁 - BGR24 pic; - AVFrame *frm = frame; - pic.w = conv_w_; - pic.h = conv_h_; - unsigned char *picData = (unsigned char*)malloc(pic.w * pic.h * 3); - conv_->copyPicture(picData, frm); - pic.data = picData; - pic.id = id; - std::lock_guard<std::mutex> l(mutex_pic_); - while(list_pic_.size() > 50){ + while(list_frm_.size() > 50){ for(int i = 0; i < 12; i++){ - auto t = list_pic_.front(); - free(t.data); - list_pic_.pop_front(); + auto t = list_frm_.front(); + av_frame_free(&t.frm); + list_frm_.pop_front(); } } - list_pic_.emplace_back(pic); - return list_pic_.size(); + list_frm_.push_back({frame,id}); + return list_frm_.size(); } int decoder::SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id){ @@ -94,7 +63,7 @@ if (!data) return -1; if (!decRef_->isVideoPkt(&data->getAVPacket())) return -2; - if (!conv_){ + if (decRef_->getCodecContext() == NULL){ if (initDecoder() != 0) return -3; } @@ -107,21 +76,50 @@ if (ret == 0){ saveFrame(frame, id); } - av_frame_free(&frame); } - void decoder::GetFrame(unsigned char **data, int *w, int *h, int64_t *id){ - std::lock_guard<std::mutex> l(mutex_pic_); - if(list_pic_.empty()){ + void decoder::GetFrame(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id){ + + AVFrame *frm = NULL; + { + std::lock_guard<std::mutex> l(mutex_frm_); + if(list_frm_.empty()){ + *data = NULL; + *w = *h = 0; + *id = -1; + return; + } + auto p = list_frm_.front(); + list_frm_.pop_front(); + frm = p.frm; + *id = p.id; + *w = frm->width; + *h = frm->height; + *format = frm->format; + } + + *length = avpicture_get_size((enum AVPixelFormat)frm->format, frm->width, frm->height); + if (*length <= 0){ + logIt("get raw frame data error"); *data = NULL; - *w = 0; - *h = 0; + *w = *h = 0; + *id = -1; return; } - auto p = list_pic_.front(); - *data = p.data; *w = p.w; *h = p.h; - *id = p.id; - list_pic_.pop_front(); + + unsigned char *picData = (unsigned char*)malloc(*length); + auto ret = avpicture_layout((const AVPicture*)frm, (enum AVPixelFormat)frm->format, frm->width, frm->height, picData, *length); + av_frame_free(&frm); + + if (ret < 0){ + *data = NULL; + *w = *h = 0; + *id = -1; + free(picData); + return; + } + + *data = picData; } } // namespace cffmpeg_wrap diff --git a/csrc/worker/decoder.hpp b/csrc/worker/decoder.hpp index ae9fba2..94bbb03 100644 --- a/csrc/worker/decoder.hpp +++ b/csrc/worker/decoder.hpp @@ -10,44 +10,40 @@ #include <condition_variable> struct AVFrame; +struct AVCodecContext; namespace ffwrapper { class FormatIn; - class cvbridge; class CodedData; } // namespace ffwrapper namespace cffmpeg_wrap { - typedef struct _pic_bgr24{ - unsigned char *data; - int w; - int h; - + typedef struct _frm{ + AVFrame *frm; int64_t id; - }BGR24; + }FRM; class decoder { private: - ffwrapper::cvbridge *conv_; - int conv_w_, conv_h_, conv_flag_; ffwrapper::FormatIn *decRef_; - std::list<BGR24> list_pic_; - std::mutex mutex_pic_; - + std::list<FRM> list_frm_; + std::mutex mutex_frm_; + private: int initDecoder(); int saveFrame(AVFrame *frame, int64_t &id); public: void Start(); int SetFrame(std::shared_ptr<ffwrapper::CodedData> data, int64_t &id); - void GetFrame(unsigned char **data, int *w, int *h, int64_t *id); + void GetFrame(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id); + public: - decoder(ffwrapper::FormatIn *dec, const int w, const int h, const int f); + explicit decoder(ffwrapper::FormatIn *dec); ~decoder(); }; diff --git a/csrc/wrapper.cpp b/csrc/wrapper.cpp index c03b54f..2643ce0 100644 --- a/csrc/wrapper.cpp +++ b/csrc/wrapper.cpp @@ -24,6 +24,8 @@ #include "worker/decoder.hpp" #include "worker/rec.hpp" +#include "CUDALERP.h" + using namespace logif; using namespace ffwrapper; @@ -40,9 +42,6 @@ Wrapper::Wrapper() :input_url_("") - ,scale_w_(0) - ,scale_h_(0) - ,scale_f_(SWS_POINT) ,audio_(false) ,gb_(0) ,cpu_(0) @@ -59,9 +58,6 @@ Wrapper::Wrapper(const char *logfile) :input_url_("") - ,scale_w_(0) - ,scale_h_(0) - ,scale_f_(SWS_POINT) ,audio_(false) ,gb_(0) ,cpu_(0) @@ -154,7 +150,7 @@ stream_ = new stream(in, 3 * in->getFPS()); // stream_->AudioSwitch(audio_); - decoder_ = new decoder(in, scale_w_, scale_h_, scale_f_); + decoder_ = new decoder(in); rec_->Load(in); if(fn_rec_lazy_) { @@ -253,9 +249,9 @@ run_dec_ = true; } - void Wrapper::GetPicDecoder(unsigned char **data, int *w, int *h, int64_t *id){ + void Wrapper::GetPicDecoder(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id){ if (decoder_){ - decoder_->GetFrame(data, w, h, id); + decoder_->GetFrame(data, w, h, format, length, id); } } @@ -427,5 +423,109 @@ return flag; } +/////////////////////////////////////////////////////////// + typedef struct _conv + { + int srcW; + int srcH; + int srcF; + int dstW; + int dstH; + cvbridge *b; + }Conv; + + void *CreateConvertor(const int srcW, const int srcH, const int srcFormat, + const int dstW, const int dstH, const int flag){ + AVPixelFormat pix_fmt = AV_PIX_FMT_BGR24; + auto bridge = new cvbridge( + srcW, srcH, srcFormat, + dstW, dstH, pix_fmt, flag); + if (!bridge) return NULL; + + Conv *c = (Conv*)malloc(sizeof(Conv)); + c->b = bridge; + c->dstW = dstW; + c->dstH = dstH; + c->srcW = srcW; + c->srcH = srcH; + c->srcF = srcFormat; + + return c; + } + + uint8_t *Convert(void *h, uint8_t *src){ + Conv *c = (Conv*)h; + + auto b = c->b; + + AVFrame *tmp_frm = av_frame_alloc(); + tmp_frm->format = (AVPixelFormat)c->srcF; + tmp_frm->width = c->srcW; + tmp_frm->height = c->srcH; + + //create a AVPicture frame from the opencv Mat input image + int ret = avpicture_fill((AVPicture *)tmp_frm, + (uint8_t *)src, + (AVPixelFormat)tmp_frm->format, + tmp_frm->width, + tmp_frm->height); + + unsigned char *picData = NULL; + if (ret > 0){ + picData = (unsigned char*)malloc(c->dstW * c->dstH * 3); + b->copyPicture(picData, tmp_frm); + } + + av_frame_free(&tmp_frm); + + return picData; + } + + void DestoryConvertor(void *h){ + Conv *c = (Conv*)h; + delete c->b; + free(c); + } + + + uint8_t* ConvertYUV2BGR(uint8_t *src, const int w, const int h, const int dst_w, const int dst_h, int *length){ + return NULL; + + // int oldw = w, oldh = h, neww = dst_w, newh = dst_h; + // // setting cache and shared modes + // cudaDeviceSetCacheConfig(cudaFuncCachePreferL1); + // cudaDeviceSetSharedMemConfig(cudaSharedMemBankSizeFourByte); + + // // allocating and transferring image and binding to texture object + // cudaChannelFormatDesc chandesc_img = cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindUnsigned); + // cudaArray* d_img_arr; + // cudaMallocArray(&d_img_arr, &chandesc_img, oldw, oldh, cudaArrayTextureGather); + // cudaMemcpyToArray(d_img_arr, 0, 0, image, oldh * oldw, cudaMemcpyHostToDevice); + // struct cudaResourceDesc resdesc_img; + // memset(&resdesc_img, 0, sizeof(resdesc_img)); + // resdesc_img.resType = cudaResourceTypeArray; + // resdesc_img.res.array.array = d_img_arr; + // struct cudaTextureDesc texdesc_img; + // memset(&texdesc_img, 0, sizeof(texdesc_img)); + // texdesc_img.addressMode[0] = cudaAddressModeClamp; + // texdesc_img.addressMode[1] = cudaAddressModeClamp; + // texdesc_img.readMode = cudaReadModeNormalizedFloat; + // texdesc_img.filterMode = cudaFilterModePoint; + // texdesc_img.normalizedCoords = 0; + // cudaTextureObject_t d_img_tex = 0; + // cudaCreateTextureObject(&d_img_tex, &resdesc_img, &texdesc_img, nullptr); + + // uint8_t* d_out = nullptr; + // cudaMalloc(&d_out, total); + + // for (int i = 0; i < warmups; ++i) CUDALERP(d_img_tex, oldw, oldh, d_out, neww, newh); + // auto start = high_resolution_clock::now(); + // for (int i = 0; i < runs; ++i) CUDALERP(d_img_tex, oldw, oldh, d_out, neww, newh); + // auto end = high_resolution_clock::now(); + // auto sum = (end - start) / runs; + + // auto h_out = new uint8_t[neww * newh]; + // cudaMemcpy(h_out, d_out, total, cudaMemcpyDeviceToHost); + } } diff --git a/csrc/wrapper.hpp b/csrc/wrapper.hpp index af976e5..13d5f7d 100644 --- a/csrc/wrapper.hpp +++ b/csrc/wrapper.hpp @@ -44,23 +44,18 @@ void BuildRecorder(const char* id,const char *dir, const int mind, const int maxd, const bool audio); int FireRecorder(const char* sid,const int64_t &id); void GetInfoRecorder(std::string &recID, int &index, std::string &path); - void ScalePicture(const int w, const int h, const int flags){ - scale_w_ = w; - scale_h_ = h; - scale_f_ = flags; - } + void GB28181(){gb_ = 1;} void CPUDec(){cpu_ = 1;} void AudioSwitch(const bool a); public: //decoder void BuildDecoder(); - void GetPicDecoder(unsigned char **data, int *w, int *h, int64_t *id); + void GetPicDecoder(unsigned char **data, int *w, int *h, int *format, int *length, int64_t *id); public: // push stream void GetPacket(unsigned char **pktData, int *size, int *key); private: // stream 鍙傛暟 std::string input_url_; - int scale_w_, scale_h_, scale_f_; bool audio_; int gb_, cpu_; bool run_dec_; @@ -80,10 +75,17 @@ }; uint8_t* Decode(const char *file, const int gb, int *w, int *h); + 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); + void *CreateConvertor(const int srcW, const int srcH, const int srcFormat, + const int dstW, const int dstH, const int flag); + uint8_t *Convert(void *h, uint8_t *src); + void DestoryConvertor(void *h); + + uint8_t* ConvertYUV2BGR(uint8_t *src, const int w, const int h, const int dst_w, const int dst_h, int *length); } #endif \ No newline at end of file diff --git a/goconv.go b/goconv.go new file mode 100644 index 0000000..459b3dd --- /dev/null +++ b/goconv.go @@ -0,0 +1,100 @@ +package goffmpeg + +/* +#include <stdlib.h> +#include "libcffmpeg.h" +*/ +import "C" +import "unsafe" + +const ( + // ScaleNone self add no scale raw frame data + ScaleNone = 0 + // ScaleFastBilinear SWS_FAST_BILINEAR + ScaleFastBilinear = 1 + // ScaleBilinear SWS_BILINEAR + ScaleBilinear = 2 + // ScaleBicubic SWS_BICUBIC + ScaleBicubic = 4 + // ScaleX SWS_X + ScaleX = 8 + // ScalePoint SWS_POINT + ScalePoint = 0x10 + // ScaleArea SWS_AREA + ScaleArea = 0x20 + // ScaleBicublin SWS_BICUBLIN + ScaleBicublin = 0x40 + // ScaleGauss SWS_GAUSS + ScaleGauss = 0x80 + // ScaleSinc SWS_SINC + ScaleSinc = 0x100 + // ScaleLancZos SWS_LANCZOS + ScaleLancZos = 0x200 + // ScaleSpline SWS_SPLINE + ScaleSpline = 0x400 +) + +// SrcFormat format +const srcFormat = 23 + +// GoConv conv +type GoConv struct { + srcW int + srcH int + dstW int + dstH int + + conv C.cconv +} + +// NewConv new conv +func NewConv(srcW, srcH, dstW, dstH, scaleFlag int) *GoConv { + c := C.wrap_fn_create_conv(C.int(srcW), C.int(srcH), C.int(srcFormat), C.int(dstW), C.int(dstH), C.int(scaleFlag)) + + if c == nil { + return nil + } + + return &GoConv{ + srcW, + srcH, + dstW, + dstH, + c, + } +} + +// Free free +func (c *GoConv) Free() { + if c.conv != nil { + C.wrap_fn_destroy_conv(c.conv) + } +} + +// ConvToPicture conv to pic +func (c *GoConv) ConvToPicture(src []byte) []byte { + if c.conv == nil { + return nil + } + + cin := C.CBytes(src) + defer C.free(cin) + + bgr := C.wrap_fn_conv(c.conv, (*C.uchar)(cin)) + defer C.free(unsafe.Pointer(bgr)) + + if bgr != nil { + return C.GoBytes(bgr, C.int(c.dstW*c.dstH*3)) + } + + return nil +} + +/////////////// for conv + +// ConvGPU conv gpu resize +func ConvGPU(in []byte, w, h, dstW, dstH int) []byte { + + return nil + +} diff --git a/godec.go b/godec.go new file mode 100644 index 0000000..a232618 --- /dev/null +++ b/godec.go @@ -0,0 +1,28 @@ +package goffmpeg + +/* +#include <stdlib.h> +#include "libcffmpeg.h" +*/ +import "C" +import "unsafe" + +// BuildDecoder build decoder +func (h *GoFFMPEG) BuildDecoder() { + C.wrap_fn_decoder(h.ffmpeg) +} + +// GetYUV get yuv data +func (h *GoFFMPEG) GetYUV() ([]byte, int, int, int64) { + var fid C.long + var length C.int + var srcW, srcH, srcF C.int + + p := C.wrap_fn_decoder_pic(h.ffmpeg, &srcW, &srcH, &srcF, &length, &fid) + if srcW == 0 || srcH == 0 { + return nil, 0, 0, 0 + } + defer C.free(unsafe.Pointer(p)) + + return C.GoBytes(p, length), int(srcW), int(srcH), int64(fid) +} diff --git a/goenc.go b/goenc.go new file mode 100644 index 0000000..3d00996 --- /dev/null +++ b/goenc.go @@ -0,0 +1,54 @@ +package goffmpeg + +/* +#include <stdlib.h> +#include "libcffmpeg.h" +*/ +import "C" + +///////////////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() { + if e.enc != nil { + 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/goffmpeg.go b/goffmpeg.go index d23bf80..dedb2bf 100644 --- a/goffmpeg.go +++ b/goffmpeg.go @@ -12,31 +12,6 @@ "unsafe" ) -const ( - // ScaleFastBilinear SWS_FAST_BILINEAR - ScaleFastBilinear = 1 - // ScaleBilinear SWS_BILINEAR - ScaleBilinear = 2 - // ScaleBicubic SWS_BICUBIC - ScaleBicubic = 4 - // ScaleX SWS_X - ScaleX = 8 - // ScalePoint SWS_POINT - ScalePoint = 0x10 - // ScaleArea SWS_AREA - ScaleArea = 0x20 - // ScaleBicublin SWS_BICUBLIN - ScaleBicublin = 0x40 - // ScaleGauss SWS_GAUSS - ScaleGauss = 0x80 - // ScaleSinc SWS_SINC - ScaleSinc = 0x100 - // ScaleLancZos SWS_LANCZOS - ScaleLancZos = 0x200 - // ScaleSpline SWS_SPLINE - ScaleSpline = 0x400 -) - var libcffmpeg C.libcffmpeg // InitFFmpeg init ffmepg @@ -59,35 +34,23 @@ } } -// Config config -type Config struct { - Scale int - Width int - Height int - GB bool - CPU bool -} - // GoFFMPEG handle for c type GoFFMPEG struct { ffmpeg C.cffmpeg } // New 2nd new -func New(conf Config) *GoFFMPEG { +func New(GB, CPU bool) *GoFFMPEG { f := C.wrap_fn_create() if f == nil { return nil } - if conf.Scale != 0 && conf.Width != 0 && conf.Height != 0 { - C.wrap_fn_scale(f, C.int(conf.Width), C.int(conf.Height), C.int(conf.Scale)) - } - if conf.GB { + if GB { C.wrap_fn_run_gb28181(f) } - if conf.CPU { + if CPU { C.wrap_fn_use_cpu(f) } @@ -97,21 +60,18 @@ } // NewWithLog log -func NewWithLog(conf Config, logfile string) *GoFFMPEG { - lf := C.CString(logfile) +func NewWithLog(GB, CPU bool, ffmpegLog string) *GoFFMPEG { + lf := C.CString(ffmpegLog) defer C.free(unsafe.Pointer(lf)) f := C.wrap_fn_create2(lf) if f == nil { return nil } - if conf.Scale != 0 && conf.Width != 0 && conf.Height != 0 { - C.wrap_fn_scale(f, C.int(conf.Width), C.int(conf.Height), C.int(conf.Scale)) - } - if conf.GB { + if GB { C.wrap_fn_run_gb28181(f) } - if conf.CPU { + if CPU { C.wrap_fn_use_cpu(f) } @@ -122,7 +82,9 @@ // Free free handle func (h *GoFFMPEG) Free() { - C.wrap_fn_destroy(h.ffmpeg) + if h.ffmpeg != nil { + C.wrap_fn_destroy(h.ffmpeg) + } } // Run ffmpeg @@ -131,161 +93,4 @@ defer C.free(unsafe.Pointer(in)) C.wrap_fn_run(h.ffmpeg, in) -} - -// FireRecorder fire recorder -func (h *GoFFMPEG) FireRecorder(sid string, id int64) { - csid := C.CString(sid) - defer C.free(unsafe.Pointer(csid)) - C.wrap_fn_fire_recorder(h.ffmpeg, csid, C.long(id)) -} - -// BuildRecorder build recorder -func (h *GoFFMPEG) BuildRecorder(sid, output string, mind, maxd int, audio bool) { - out := C.CString(output) - defer C.free(unsafe.Pointer(out)) - csid := C.CString(sid) - defer C.free(unsafe.Pointer(csid)) - - a := 0 - if audio { - a = 1 - } - C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd), C.int(a)) -} - -// GetInfoRecorder info -func (h *GoFFMPEG) GetInfoRecorder() (string, int, string) { - var i C.int = -1 - - var id *C.char - var idl C.int - - var p *C.char - var pl C.int - - C.wrap_fn_info_recorder(h.ffmpeg, &i, &id, &idl, &p, &pl) - // if p == nil { - // return -1, "" - // } - gID := C.GoString(id) - C.free(unsafe.Pointer(id)) - path := C.GoString(p) - C.free(unsafe.Pointer(p)) - - // fmt.Println("Go get info : ", path, " len: ", l) - - return gID, int(i), path -} - -// BuildDecoder build decoder -func (h *GoFFMPEG) BuildDecoder() { - C.wrap_fn_decoder(h.ffmpeg) -} - -// GetPicDecoder get pic from decoder -func (h *GoFFMPEG) GetPicDecoder() ([]byte, int, int, int64) { - var width C.int - var height C.int - var fid C.long - - p := C.wrap_fn_decoder_pic(h.ffmpeg, &width, &height, &fid) - if width == 0 && height == 0 { - return nil, 0, 0, 0 - } - defer C.free(unsafe.Pointer(p)) - d := C.GoBytes(p, width*height*3) - wid := int(width) - hei := int(height) - gfid := int64(fid) - return d, wid, hei, gfid -} - -//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 -} - -/////////////// for decoder - -// Decode decode jpeg file -// return val: -1 open error; -2, find stream error; -3, converter create error -func Decode(input string, gb bool) ([]byte, int, int) { - in := C.CString(input) - defer C.free(unsafe.Pointer(in)) - - withGB := 0 - if gb { - withGB = 1 - } - - var width C.int - var height C.int - p := C.wrap_fn_decode(in, C.int(withGB), &width, &height) - defer C.free(p) - - if width > 0 && height > 0 { - data := C.GoBytes(p, width*height*3) - wid := int(width) - hei := int(height) - return data, wid, hei - } - return nil, int(width), int(height) -} - -///////////////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/gojpeg.go b/gojpeg.go new file mode 100644 index 0000000..6cc855d --- /dev/null +++ b/gojpeg.go @@ -0,0 +1,36 @@ +package goffmpeg + +/* +#include <stdlib.h> +#include "libcffmpeg.h" +*/ +import "C" + +import "unsafe" + +/////////////// for decoder + +// Decode decode jpeg file +// return val: -1 open error; -2, find stream error; -3, converter create error +func Decode(input string, gb bool) ([]byte, int, int) { + in := C.CString(input) + defer C.free(unsafe.Pointer(in)) + + withGB := 0 + if gb { + withGB = 1 + } + + var width C.int + var height C.int + p := C.wrap_fn_decode(in, C.int(withGB), &width, &height) + defer C.free(p) + + if width > 0 && height > 0 { + data := C.GoBytes(p, width*height*3) + wid := int(width) + hei := int(height) + return data, wid, hei + } + return nil, int(width), int(height) +} diff --git a/gorec.go b/gorec.go new file mode 100644 index 0000000..dcf0f5e --- /dev/null +++ b/gorec.go @@ -0,0 +1,54 @@ +package goffmpeg + +/* +#include <stdlib.h> +#include "libcffmpeg.h" +*/ +import "C" + +import "unsafe" + +// FireRecorder fire recorder +func (h *GoFFMPEG) FireRecorder(sid string, id int64) { + csid := C.CString(sid) + defer C.free(unsafe.Pointer(csid)) + C.wrap_fn_fire_recorder(h.ffmpeg, csid, C.long(id)) +} + +// BuildRecorder build recorder +func (h *GoFFMPEG) BuildRecorder(sid, output string, mind, maxd int, audio bool) { + out := C.CString(output) + defer C.free(unsafe.Pointer(out)) + csid := C.CString(sid) + defer C.free(unsafe.Pointer(csid)) + + a := 0 + if audio { + a = 1 + } + C.wrap_fn_recorder(h.ffmpeg, csid, out, C.int(mind), C.int(maxd), C.int(a)) +} + +// GetInfoRecorder info +func (h *GoFFMPEG) GetInfoRecorder() (string, int, string) { + var i C.int = -1 + + var id *C.char + var idl C.int + + var p *C.char + var pl C.int + + C.wrap_fn_info_recorder(h.ffmpeg, &i, &id, &idl, &p, &pl) + // if p == nil { + // return -1, "" + // } + gID := C.GoString(id) + C.free(unsafe.Pointer(id)) + path := C.GoString(p) + C.free(unsafe.Pointer(p)) + + // fmt.Println("Go get info : ", path, " len: ", l) + + return gID, int(i), path +} diff --git a/gostream.go b/gostream.go new file mode 100644 index 0000000..6345ebd --- /dev/null +++ b/gostream.go @@ -0,0 +1,26 @@ +package goffmpeg + +/* +#include <stdlib.h> +#include "libcffmpeg.h" +*/ +import "C" + +import "unsafe" + +//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 +} diff --git a/libcffmpeg.c b/libcffmpeg.c index 69fcbb9..2414a16 100644 --- a/libcffmpeg.c +++ b/libcffmpeg.c @@ -25,8 +25,6 @@ release_if_err(fn_destroy, lib); fn_run = (lib_cffmpeg_run)dlsym(lib, "c_ffmpeg_run"); release_if_err(fn_run, lib); - fn_scale = (lib_cffmpeg_scale)dlsym(lib, "c_ffmpeg_scale"); - release_if_err(fn_scale, lib); fn_gb28181 = (lib_cffmpeg_gb28181)dlsym(lib, "c_ffmpeg_run_gb28181"); release_if_err(fn_gb28181, lib); fn_cpu = (lib_cffmpeg_cpu)dlsym(lib, "c_ffmepg_use_cpu"); @@ -52,6 +50,16 @@ release_if_err(fn_destroy_encoder, lib); fn_encode = (lib_cffmpeg_encode)dlsym(lib, "c_ffmpeg_encode"); release_if_err(fn_encode, lib); + + fn_create_conv = (lib_cffmpeg_create_conv)dlsym(lib, "c_ffmpeg_create_conv"); + release_if_err(fn_create_conv, lib); + fn_destroy_conv = (lib_cffmpeg_destroy_conv)dlsym(lib, "c_ffmpeg_destroy_conv"); + release_if_err(fn_destroy_conv, lib); + fn_conv = (lib_cffmpeg_conv)dlsym(lib, "c_ffmpeg_conv"); + release_if_err(fn_conv, lib); + + fn_gpu_conv = (lib_gpu_conv)dlsym(lib, "c_gpu_conv"); + release_if_err(fn_gpu_conv, lib); }else{ printf("dlopen - %s\n", dlerror()); @@ -81,10 +89,6 @@ fn_run(h, input); } -void wrap_fn_scale(const cffmpeg h, const int wid, const int hei, const int flags){ - fn_scale(h, wid, hei, flags); -} - void wrap_fn_run_gb28181(const cffmpeg h){ fn_gb28181(h); } @@ -109,8 +113,8 @@ fn_decoder(h); } -void* wrap_fn_decoder_pic(const cffmpeg h, int* wid, int* hei, int64_t *id){ - return fn_decoder_pic(h, wid, hei, id); +void* wrap_fn_decoder_pic(const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id){ + return fn_decoder_pic(h, wid, hei, format, length, id); } void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key){ @@ -120,6 +124,10 @@ // return val: -1 open error; -2, find stream error; -3, converter create error void* wrap_fn_decode(const char* file, const int gb, int* wid, int* hei){ return fn_decode(file, gb, wid, hei); +} + +void* wran_fn_gpu_conv(void *in, const int w, const int h, const int dst_w, const int dst_h, int *length){ + return fn_gpu_conv(in, w, h, dst_w, dst_h, length); } // for encoder @@ -141,3 +149,16 @@ *key = 0; return NULL; } + +// for conv +cconv wrap_fn_create_conv(const int srcW, const int srcH, const int srcFormat, + const int dstW, const int dstH, const int flag){ + return fn_create_conv(srcW, srcH, srcFormat, dstW, dstH, flag); +} + +void wrap_fn_destroy_conv(const cconv h){ + fn_destroy_conv(h); +} +void* wrap_fn_conv(const cconv h, uint8_t *in){ + return fn_conv(h, in); +} diff --git a/libcffmpeg.h b/libcffmpeg.h index 5b43da3..44d82b2 100644 --- a/libcffmpeg.h +++ b/libcffmpeg.h @@ -14,22 +14,21 @@ typedef cffmpeg(*lib_cffmpeg_create2)(const char*); typedef void (*lib_cffmpeg_destroy)(const cffmpeg); typedef void (*lib_cffmpeg_run)(const cffmpeg, const char*); -typedef void (*lib_cffmpeg_scale)(const cffmpeg, const int, const int, const int); typedef void (*lib_cffmpeg_gb28181)(const cffmpeg); typedef void (*lib_cffmpeg_cpu)(const cffmpeg); typedef void (*lib_cffmpeg_recorder)(const cffmpeg, const char*, const char*, int, int, int); typedef void (*lib_cffmpeg_fire_recorder)(const cffmpeg, const char*, const int64_t); typedef void (*lib_cffmpeg_info_recorder)(const cffmpeg, int*, char**, int*, char**, int*); typedef void (*lib_cffmpeg_decoder)(const cffmpeg); -typedef void*(*lib_cffmpeg_pic)(const cffmpeg, int*, int*, int64_t*); +typedef void*(*lib_cffmpeg_pic)(const cffmpeg, int*, int*, int*, int*, int64_t*); typedef void*(*lib_cffmpeg_avpacket)(const cffmpeg, int*, int*); typedef void*(*lib_cffmpeg_decode)(const char*, const int, int*, int*); +typedef void*(*lib_gpu_conv)(void*, const int, const int, const int, const int, int *); static lib_cffmpeg_create fn_create = NULL; static lib_cffmpeg_create2 fn_create2 = NULL; static lib_cffmpeg_destroy fn_destroy = NULL; static lib_cffmpeg_run fn_run = NULL; -static lib_cffmpeg_scale fn_scale = NULL; static lib_cffmpeg_gb28181 fn_gb28181 = NULL; static lib_cffmpeg_cpu fn_cpu = NULL; static lib_cffmpeg_recorder fn_recorder = NULL; @@ -39,6 +38,7 @@ static lib_cffmpeg_pic fn_decoder_pic = NULL; static lib_cffmpeg_avpacket fn_get_avpacket = NULL; static lib_cffmpeg_decode fn_decode = NULL; +static lib_gpu_conv fn_gpu_conv = NULL; typedef void* libcffmpeg; libcffmpeg init_libcffmpeg(const char *so_file); @@ -48,21 +48,18 @@ cffmpeg wrap_fn_create2(const char *logfile); void wrap_fn_destroy(const cffmpeg h); void wrap_fn_run(const cffmpeg h, const char* input); -void wrap_fn_scale(const cffmpeg h, const int wid, const int hei, const int flags); void wrap_fn_run_gb28181(const cffmpeg h); void wrap_fn_use_cpu(const cffmpeg h); void wrap_fn_recorder(const cffmpeg h, const char* id, const char* dir, int mind, int maxd, int audio); void wrap_fn_fire_recorder(const cffmpeg h, const char *sid, const int64_t id); void wrap_fn_info_recorder(const cffmpeg, int* index, char** recid, int* recidLen, char** fpath, int* pathLen); void wrap_fn_decoder(const cffmpeg h); -void* wrap_fn_decoder_pic(const cffmpeg h, int* wid, int* hei, int64_t *id); +void* wrap_fn_decoder_pic(const cffmpeg h, int *wid, int *hei, int *format, int *length, int64_t *id); void* wrap_fn_get_avpacket(const cffmpeg h, int* size, int* key); void* wrap_fn_decode(const char* file, const int gb, int* wid, int* hei); - - +void* wran_fn_gpu_conv(void *in, const int w, const int h, const int dst_w, const int dst_h, int *length); // 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); @@ -75,6 +72,22 @@ 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); + +// for conv +typedef void *cconv; +typedef cconv (*lib_cffmpeg_create_conv)(const int, const int, const int, const int, const int, const int); +typedef void* (*lib_cffmpeg_conv)(const cconv, uint8_t *in); +typedef void (*lib_cffmpeg_destroy_conv)(const cconv); + +static lib_cffmpeg_create_conv fn_create_conv = NULL; +static lib_cffmpeg_destroy_conv fn_destroy_conv = NULL; +static lib_cffmpeg_conv fn_conv = NULL; + +cconv wrap_fn_create_conv(const int srcW, const int srcH, const int srcFormat, + const int dstW, const int dstH, const int flag); +void wrap_fn_destroy_conv(const cconv h); +void* wrap_fn_conv(const cconv h, uint8_t *in); + #ifdef __cplusplus } #endif -- Gitblit v1.8.0