video analysis2.0拆分,ffmpeg封装go接口库
zhangmeng
2019-10-09 68a19a73681301c6712e10d55bc64324716dbd24
split scale
8个文件已添加
11个文件已修改
1042 ■■■■■ 已修改文件
CMakeLists.txt 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cffmpeg.h 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/cffmpeg.cpp 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/ffmpeg/configure/conf.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/gpu-conv/CUDALERP.cu 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/gpu-conv/CUDALERP.h 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/decoder.cpp 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/worker/decoder.hpp 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.cpp 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
csrc/wrapper.hpp 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
goconv.go 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
godec.go 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
goenc.go 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
goffmpeg.go 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
gojpeg.go 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
gorec.go 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
gostream.go 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libcffmpeg.c 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libcffmpeg.h 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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)
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
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);
}
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){
csrc/gpu-conv/CUDALERP.cu
New file
@@ -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();
}
csrc/gpu-conv/CUDALERP.h
New file
@@ -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);
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
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();
    };
    
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);
    }
}
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
goconv.go
New file
@@ -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
}
godec.go
New file
@@ -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)
}
goenc.go
New file
@@ -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
}
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
}
gojpeg.go
New file
@@ -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)
}
gorec.go
New file
@@ -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
}
gostream.go
New file
@@ -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
}
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);
}
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