以下是开发过程中遇到的C++的一些特性记录. tags: C/C++, Decode, GPU, Python category: Documents

当前目的开发c++硬解码并使用python调用其动态库实现一次抽一次帧.

以下是开发过程中遇到的C++的一些特性记录.

1. 二级指针初始化与释放

  • 二级指针需要初始化两次, 分别是二级指针和一级指针

    int **a;
    a = (int *)malloc(num * sizeof(int));
    for (int32_t i = 0; i < num; i++)
    {
    	a[i] = (int)malloc(num_2 * sizeof(int));
    }
    // or
    int **a;
    a = new int*[num];
    for (int32_t i = 0; i < num; i++)
    {
    	a[i] = new int[num_2];
    }
    
  • 释放指针, 需要先释放一级指针再释放二级指针, 如果先释放二级指针, 一级指针的地址会丢失, 导致内存泄漏.

    for(i = 0; i < 100; i++)
    {
     delete []temp[i];
    }
    delete []temp;
    

2. C++结构体与python传值

  • c++定义结构体对象

    struct VideoPreprocessInf
    {
        int64_t frame_index = 0;
        int32_t ori_w = 0;
        int32_t ori_h = 0;
        int32_t resize_w = 0;
        int32_t resize_h = 0;
        int32_t img_w = 0;
        int32_t img_h = 0;
        int32_t pad_w = 0;
        int32_t pad_h = 0;
        int32_t roi_start_w = 0;
        int32_t roi_start_h = 0;
        int32_t roi_w = 0;
        int32_t roi_h = 0;
        int32_t channel = 3;
        int32_t output_size = 0;
        bool do_crop_middle = false;
        bool do_padding = false;
        float scale = 1.f;
        double mean[3] = {0.0f, 0.0f, 0.0f};
        double standard[3] = {1.f, 1.f, 1.f};
    
    } video_preprocess_inf;
    
  • python定义同结构体对象

    class VideoPreprocessInf(Structure):
        _fields_ = (
            ('frame_index', c_longlong),
            ('ori_w ', c_int),
            ('ori_h ', c_int),
            ('resize_w ', c_int),
            ('resize_h ', c_int),
            ('img_w ', c_int),
            ('img_h ', c_int),
            ('pad_w ', c_int),
            ('pad_h ', c_int),
            ('roi_start_w ', c_int),
            ('roi_start_h ', c_int),
            ('roi_w ', c_int),
            ('roi_h ', c_int),
            ('channel', c_int),
            ('output_size', c_int),
            ('do_crop_middle', c_bool),
            ('do_padding', c_bool),
            ('scale', c_float),
            ('mean', c_double * 3),
            ('standard', c_double * 3),
        )
    
  1. python端初始化结构体示例

    • 之后就可以输入C++动态库函数

      inf_list = [0, 0, 0, resize_w, resize_h, 0, 0, 0, 0, 0, 0, 0, 0,
                      channel, 0, do_crop_middle, do_padding, 1.0, mean, standard]
      video_preprocess_inf = VideoPreprocessInf(*inf_list)
      
  2. C++端初始化结构体

    • 全局结构体只需要在结构体结尾加上变量, 其他地方只要使用变量即可

      struct VideoPreprocessInf
      {
          int64_t frame_index = 0;
      	  ...
      } video_preprocess_inf;
      
    • 需要当成调用多次的时候初始化:

      struct VideoPreprocessInf
      {
          int64_t frame_index = 0;
      	  ...
      };
      
      //初始化
      VideoPreprocessInf vpi = {
      		.frame_index = 1,
      		...
      };
      // 或者
      VideoPreprocessInf vpi = {
      		frame_index:1,
      		...
      };
      // 或者给需要修改的元素各自赋值
      VideoPreprocessInf vpi;
      vpi.frame_index = 1;
      ...
      

3. C++头文件使用C风格的函数

extern "C"
{
	int xxxx();
}

4. struct和typedef struct的区别

struct和typedef struct彻底明白了

Difference between ‘struct’ and ’typedef struct’ in C++?

5. 实现python调用c++单步抽帧

  • 使用全局指针, 函数中全局指针指向new class demuxer 和 decoder

    Demuxer *demuxer_p = nullptr;
    DlDecoder *decoder_p = nullptr;
    
    VideoInitInf init_demuxer_decoder(char *inputFilename, int gpu_id)
    { // 初始化数据流提取器和解码器, 使用全局指针指向它们
      demuxer_p = new Demuxer(inputFilename);
      decoder_p = new DlDecoder(gpu_id, 0xf, 0xf, true, demuxer_p->GetVideoCodec());
    	...
    }
    
    float *video_decoder(VideoPreprocessInf video_preprocess_inf, bool do_extract)
    { // 单步抽帧
    	demuxer_p->Demux(&pVideo, &nVideoBytes);
      decoder_p->Decode(pVideo, nVideoBytes, &output_frames, &output_frame_count, 0);
    	...
    }
    
    void release_demuxer_decoder()
    { // 如果指针指向内存地址, 则清除缓存, 重置指针
    	if (demuxer_p)
      {
        delete demuxer_p;
        demuxer_p = nullptr;
      }
      if (decoder_p)
      {
        delete decoder_p;
        decoder_p = nullptr;
      }
    	...
    }
    

6. C++ 11 Lambda表达式

遇到符号[=]

C++ 11 Lambda表达式

7. CUDA C编程

如何在 CUDA C/C++ 中实现数据传输的重叠

cudaMemcpyAsync等知识

7.1. python c++ 混合编程

华为开发者论坛

环境

https://github.com/pybind/pybind11

pip install pybind11
pip install pytest

直接使用pybind11文件夹, 直接放在项目文件夹根目录下, 和CMakeLists.txt还有cu.cc文件放一起.

git clone https://github.com/pybind/pybind11.git

7.1.1. cmakelists编译的过程中不停循环不终止问题

cmakelists循环执行_阿伟跑呀的博客-CSDN博客

7.2. C++ 传承python方法2

7.3. python 使用ctype与C++通信

C++编译 Cmakelists.txt

SET (LIBHELLO_SRC ${SRCS})
ADD_LIBRARY (AppDec SHARED ${LIBHELLO_SRC})

# 输出动态库
install(TARGETS AppDec
        LIBRARY DESTINATION ${CMAKE_BINARY_DIR}/bin
        )