以下是开发过程中遇到的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), )
-
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)
-
-
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的区别
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表达式
遇到符号[=]
7. CUDA 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编译的过程中不停循环不终止问题
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
)