Commit a25d4e5da5104ed8624819b5ca80da83f4741d31

Authored by ming
2 parents ecb0badb 429e8f86

Merge branch 'dev-cmhu' of 192.168.10.182:ming/FFNvDecoder into dev-cmhu

Conflicts:
	.vscode/launch.json
	build/Makefile
	src/demo/main_dvpp.cpp
	src/interface/FFNvDecoderManager.cpp
Showing 65 changed files with 3769 additions and 647 deletions
.gitignore
1 1 ffmpeg-4.2.2/
2   -.vscode/
3 2 bin/
4 3 .idea/
5 4  
6   -3rdparty/
7 5 \ No newline at end of file
  6 +3rdparty/*
  7 +src/build/*
... ...
.vscode/launch.json
... ... @@ -2,31 +2,13 @@
2 2 "version": "0.2.0",
3 3 "configurations": [
4 4 {
5   - "name": "(gdb) Launch",
  5 + "name": "dvpp",
6 6 "type": "cppdbg",
7 7 "request": "launch",
8 8 "program": "${workspaceFolder}/bin/lib/test",
9 9 "args": ["rtsp://192.168.10.4:8554/street","3", "30012"],
10 10 "stopAtEntry": false,
11   - "cwd": "${workspaceFolder}/bin/lib",
12   - "environment": [],
13   - "externalConsole": false,
14   - "MIMode": "gdb",
15   - "setupCommands": [
16   - {
17   - "description": "Enable pretty-printing for gdb",
18   - "text": "-enable-pretty-printing",
19   - "ignoreFailures": true
20   - }
21   - ]
22   - },{
23   - "name": "ffmpeg",
24   - "type": "cppdbg",
25   - "request": "launch",
26   - "program": "${workspaceFolder}/bin/lib/ffmpeg_g",
27   - "args": ["-vsync","0","-hwaccel","cuvid","-hwaccel_device","1","-c:v","h264_cuvid","-i","rtmp://192.168.10.56:1935/objecteye/116","-c:a","copy","-vf","scale_npp=800:480","-c:v","h264","/mnt/data/cmhu/FFNvDecoder/data/output1.mp4"],
28   - "stopAtEntry": false,
29   - "cwd": "${workspaceFolder}/bin/lib",
  11 + "cwd": "${workspaceFolder}/src/build/bin",
30 12 "environment": [],
31 13 "externalConsole": false,
32 14 "MIMode": "gdb",
... ... @@ -38,11 +20,11 @@
38 20 }
39 21 ]
40 22 },{
41   - "name": "jrtp",
  23 + "name": "nvdec",
42 24 "type": "cppdbg",
43 25 "request": "launch",
44   - "program": "${workspaceFolder}/bin/lib/jrtp_exe",
45   - "args": ["40030","t"],
  26 + "program": "${workspaceFolder}/bin/lib/demo",
  27 + "args": ["/mnt/data/cmhu/data/caishenkezhan.mp4","0", "0"],
46 28 "stopAtEntry": false,
47 29 "cwd": "${workspaceFolder}/bin/lib",
48 30 "environment": [],
... ...
.vscode/settings.json
... ... @@ -62,6 +62,14 @@
62 62 "cfenv": "cpp",
63 63 "cinttypes": "cpp",
64 64 "__nullptr": "cpp",
65   - "list": "cpp"
  65 + "list": "cpp",
  66 + "hash_map": "cpp",
  67 + "hash_set": "cpp",
  68 + "complex": "cpp",
  69 + "unordered_set": "cpp",
  70 + "regex": "cpp",
  71 + "shared_mutex": "cpp",
  72 + "variant": "cpp",
  73 + "ios": "cpp"
66 74 }
67 75 }
68 76 \ No newline at end of file
... ...
README.md
1   -#### ffmpeg编译配置
  1 +#### 基于CUDA的ffmpeg编译配置
2 2 1. 安装cuda
3 3 2. 安装 nv-codec-headers
4 4 支持 cuvid 需要安装 nv-codec-headers, 进入 nv-codec-headers 文件夹后以sudo权限make && make install即可
... ... @@ -11,5 +11,10 @@
11 11 --enable-debug --extra-cflags=-g --extra-ldflags=-g --disable-optimizations --disable-stripping
12 12 ~~~
13 13  
  14 +#### 普通ffmpeg编译配置
  15 +~~~
  16 +./configure --enable-debug --extra-cflags=-g --extra-ldflags=-g --disable-optimizations --disable-stripping --disable-x86asm --enable-nonfree --disable-vaapi --extra-cflags=-fPIC --enable-shared --enable-pic --enable-ffplay --prefix=../bin
  17 +~~~
  18 +
14 19 #### SDK说明
15 20 1. 对外接口主要是 FFNvDecoderManager 类,可支持多个解码器;也可直接使用 FFNvDecoder ,但是不建议,FFNvDecoderManager已经封装了 FFNvDecoder 的接口
16 21 \ No newline at end of file
... ...
build/Makefile
1   -XX = g++
  1 +# 项目根目录
  2 +TOP_DIR:=$(patsubst %/, %, $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
  3 +export TOP_DIR
2 4  
3   -CUDA_ROOT = /usr/local/cuda-11.1
4   -NVCC = $(CUDA_ROOT)/bin/nvcc
5   -
6   -
7   -PROJECT_ROOT= /mnt/data/cmhu/FFNvDecoder
  5 +# 各项目录
  6 +BUILD_DIR:=$(TOP_DIR)/build
  7 +BIN_DIR:=$(BUILD_DIR)/bin
  8 +export BUILD_DIR
8 9  
9   -DEPEND_DIR = $(PROJECT_ROOT)/bin
10   -SRC_ROOT = $(PROJECT_ROOT)/src
  10 +PROJECT_ROOT= /home/huchunming/FFNvDecoder
11 11 THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty
  12 +export PROJECT_ROOT THIRDPARTY_ROOT
12 13  
  14 +CUDA_ROOT = /usr/local/cuda-11.1
  15 +export CUDA_ROOT
13 16  
14   -TARGET= $(DEPEND_DIR)/lib/test
15   -
16   -
  17 +FFMPEG_DIR = $(PROJECT_ROOT)/bin
17 18 SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release
18   -JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export
19   -CURL_ROOT = $(THIRDPARTY_ROOT)/curl/bin
20 19  
  20 +#编译器
  21 +CXX:=g++
21 22  
22 23 INCLUDE= -I $(DEPEND_DIR)/include \
23 24 -I $(CUDA_ROOT)/include \
... ... @@ -37,34 +38,40 @@ LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilte
37 38 -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \
38 39 -L $(CURL_ROOT)/lib -l:libcurl.a \
39 40  
40   -CFLAGS= -g -fPIC -O0 $(INCLUDE) -pthread -lrt -lz -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl
41   - # -DUNICODE -D_UNICODE
  41 +export CXX INCS MACROS LIBS
42 42  
43   -NFLAGS_LIB=-g -c -shared -Xcompiler -fPIC -Xcompiler -fvisibility=hidden
44   -NFLAGS = $(NFLAGS_LIB) $(INCLUDE) -std=c++11
  43 +MACROS:= -DUSE_DVPP
45 44  
46   -SRCS:=$(wildcard $(SRC_ROOT)/*.cpp) \
47   - $(wildcard $(SRC_ROOT)/gb28181/*.cpp)
48   -OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))
  45 +# 各个模块
  46 +MODULES:= dvpp interface demo
49 47  
50   -CU_SOURCES = $(wildcard ${SRC_ROOT}/*.cu)
51   -CU_OBJS = $(patsubst %.cu, %.o, $(notdir $(CU_SOURCES)))
  48 +# 各个模块对应的库
  49 +# MODULE_LIBS:=$(BUILD_DIR)/nvdec/lib/nvdec.a\
  50 +# $(BUILD_DIR)/nvdec/lib/gb28181.a\
  51 +# $(BUILD_DIR)/interface/lib/interface.a\
52 52  
  53 +# 最终目标文件
  54 +TARGET:=$(BIN_DIR)/test
53 55  
54   -$(TARGET):$(OBJS) $(CU_OBJS)
55   - rm -f $(TARGET)
56   - $(XX) -o $@ $^ $(CFLAGS) $(LIBSPATH) $(LIBS) -Wwrite-strings
57   - rm -f *.o
  56 +# 默认最终目标
  57 +.PHONY:all
  58 +all:$(TARGET)
58 59  
59   -%.o:$(SRC_ROOT)/%.cpp
60   - $(XX) $(CFLAGS) -c $<
  60 +# 最终目标依赖关系
  61 +$(TARGET):FORCE | $(BIN_DIR)
  62 + @for n in $(MODULES); do make -s -f $(TOP_DIR)/$$n/Makefile MODULE=$$n || exit "$$?"; done
  63 +# @echo -e "\e[32m""Linking executable $(TARGET)""\e[0m"
  64 +#@$(LD) $(LDFLAGS) -o $@ $(MODULE_LIBS) $(LIBS)
61 65  
62   -%.o:$(SRC_ROOT)/gb28181/%.cpp
63   - $(XX) $(CFLAGS) -c $<
  66 +# 若没有bin目录则自动生成
  67 +$(BIN_DIR):
  68 + @mkdir -p $@
64 69  
65   -%.o:$(SRC_ROOT)/%.cu
66   - @echo "#######################CU_OBJS:$@###############"
67   - $(NVCC) $(NFLAGS) -o $@ $<
  70 +# 强制执行命令
  71 +.PHONY:FORCE
  72 +FORCE:
68 73  
  74 +# make clean直接删除整个build目录
  75 +.PHONY:clean
69 76 clean:
70   - rm -f *.o $(TARGET)
71 77 \ No newline at end of file
  78 + @rm -rf $(BUILD_DIR)
... ...
src/AbstractDecoder.cpp deleted
1   -#include "AbstractDecoder.h"
2   -
3   -#include "logger.hpp"
4   -#include "GpuRgbMemory.hpp"
5   -#include "cuda_kernels.h"
6   -
7   -#include "utiltools.hpp"
8   -
9   -
10   -FFImgInfo* AbstractDecoder::snapshot(){
11   -
12   - // 锁住停止队列消耗
13   - std::lock_guard<std::mutex> l(m_snapshot_mutex);
14   -
15   - AVFrame * gpuFrame = nullptr;
16   -
17   - bool bFirst = true;
18   - while(true){
19   - m_queue_mutex.lock();
20   - if(mFrameQueue.size() <= 0){
21   - m_queue_mutex.unlock();
22   - if(bFirst){
23   - std::this_thread::sleep_for(std::chrono::milliseconds(100));
24   - bFirst = false;
25   - continue;
26   - }else{
27   - // 再进来说明前面已经等了 100 ms
28   - // 100 ms都没有等到解码数据,则退出
29   - return nullptr;
30   - }
31   - }
32   -
33   - // 队列中数据大于1
34   - gpuFrame = mFrameQueue.front();
35   - m_queue_mutex.unlock();
36   - break;
37   - }
38   -
39   - if (gpuFrame != nullptr && gpuFrame->format == AV_PIX_FMT_CUDA ){
40   - LOG_DEBUG("decode task: gpuid: {} width: {} height: {}", m_cfg.gpuid, gpuFrame->width, gpuFrame->height);
41   - GpuRgbMemory* gpuMem = new GpuRgbMemory(3, gpuFrame->width, gpuFrame->height, getName(), m_cfg.gpuid , true);
42   -
43   - if (gpuMem->getMem() == nullptr){
44   - LOG_ERROR("new GpuRgbMemory failed !!!");
45   - return nullptr;
46   - }
47   -
48   - cudaSetDevice(atoi(m_cfg.gpuid.c_str()));
49   - cuda_common::setColorSpace( ITU_709, 0 );
50   - cudaError_t cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], gpuMem->getMem(), gpuFrame->width, gpuFrame->height);
51   - cudaDeviceSynchronize();
52   - if (cudaStatus != cudaSuccess) {
53   - LOG_ERROR("CUDAToBGR failed failed !!!");
54   - return nullptr;
55   - }
56   -
57   - unsigned char * pHwRgb = gpuMem->getMem();
58   - int channel = gpuMem->getChannel();
59   - int width = gpuMem->getWidth();
60   - int height = gpuMem->getHeight();
61   -
62   - if (pHwRgb != nullptr && channel > 0 && width > 0 && height > 0){
63   - int nSize = channel * height * width;
64   -
65   - LOG_INFO("channel:{} height:{} width:{}", channel, height, width);
66   - // unsigned char* cpu_data = new unsigned char[nSize];
67   -
68   - unsigned char* cpu_data = (unsigned char *)av_malloc(nSize * sizeof(unsigned char));
69   -
70   - cudaMemcpy(cpu_data, pHwRgb, nSize * sizeof(unsigned char), cudaMemcpyDeviceToHost);
71   - cudaDeviceSynchronize();
72   -
73   - delete gpuMem;
74   - gpuMem = nullptr;
75   -
76   - FFImgInfo* imgInfo = new FFImgInfo();
77   - imgInfo->dec_name = m_dec_name;
78   - imgInfo->pData = cpu_data;
79   - imgInfo->height = height;
80   - imgInfo->width = width;
81   - imgInfo->timestamp = UtilTools::get_cur_time_ms();
82   - imgInfo->index = m_index;
83   -
84   - m_index++;
85   -
86   - return imgInfo;
87   - }
88   -
89   - delete gpuMem;
90   - gpuMem = nullptr;
91   - }
92   -
93   - return nullptr;
94   -}
95   -
96   -bool AbstractDecoder::isSnapTime(){
97   - if(m_snap_time_interval <= 0){
98   - return false;
99   - }
100   - long cur_time = UtilTools::get_cur_time_ms();
101   - if(cur_time - m_last_snap_time > m_snap_time_interval){
102   - return true;
103   - }
104   - return false;
105   -}
106   -
107   -void AbstractDecoder::updateLastSnapTime(){
108   - m_last_snap_time = UtilTools::get_cur_time_ms();
109   -}
110   -
111   -void AbstractDecoder::setSnapTimeInterval(long interval){
112   - m_snap_time_interval = interval;
113   - m_last_snap_time = UtilTools::get_cur_time_ms();
114   -}
115 0 \ No newline at end of file
src/Makefile.bak 0 → 100644
  1 +XX = g++
  2 +
  3 +CUDA_ROOT = /usr/local/cuda-11.1
  4 +NVCC = $(CUDA_ROOT)/bin/nvcc
  5 +
  6 +
  7 +PROJECT_ROOT= /home/huchunming/FFNvDecoder
  8 +
  9 +DEPEND_DIR = $(PROJECT_ROOT)/bin
  10 +SRC_ROOT = $(PROJECT_ROOT)/src
  11 +
  12 +TARGET= $(DEPEND_DIR)/lib/test
  13 +
  14 +THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty
  15 +SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release
  16 +JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export
  17 +
  18 +
  19 +INCLUDE= -I $(DEPEND_DIR)/include \
  20 + -I $(CUDA_ROOT)/include \
  21 + -I $(SRC_ROOT)/common/inc \
  22 + -I $(SRC_ROOT)/common/UtilNPP \
  23 + -I $(SRC_ROOT)\
  24 + -I $(SPDLOG_ROOT)/include \
  25 + -I $(SRC_ROOT)/gb28181 \
  26 + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \
  27 + -I $(JRTP_ROOT)/jthread/include/jthread
  28 +
  29 +LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \
  30 + -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \
  31 + -L $(SPDLOG_ROOT) -l:libspdlog.a \
  32 + -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \
  33 + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a
  34 +
  35 +CFLAGS= -g -fPIC -O0 $(INCLUDE) -pthread -lrt -lz -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl
  36 + # -DUNICODE -D_UNICODE
  37 +
  38 +NFLAGS_LIB=-g -c -shared -Xcompiler -fPIC -Xcompiler -fvisibility=hidden
  39 +NFLAGS = $(NFLAGS_LIB) $(INCLUDE) -std=c++11
  40 +
  41 +SRCS:=$(wildcard $(SRC_ROOT)/nvdec/*.cpp) \
  42 + $(wildcard $(SRC_ROOT)/gb28181/*.cpp) \
  43 + $(wildcard $(SRC_ROOT)/dvpp/*.cpp)
  44 +OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))
  45 +
  46 +CU_SOURCES = $(wildcard ${SRC_ROOT}/*.cu)
  47 +CU_OBJS = $(patsubst %.cu, %.o, $(notdir $(CU_SOURCES)))
  48 +
  49 +
  50 +$(TARGET):$(OBJS) $(CU_OBJS)
  51 + rm -f $(TARGET)
  52 + $(XX) -o $@ $^ $(CFLAGS) $(LIBSPATH) $(LIBS) -Wwrite-strings
  53 + rm -f *.o
  54 +
  55 +# %.o:$(SRC_ROOT)/nvdec/%.cpp
  56 +# $(XX) $(CFLAGS) -c $<
  57 +
  58 +%.o:$(SRC_ROOT)/gb28181/%.cpp
  59 + $(XX) $(CFLAGS) -c $<
  60 +
  61 +%.o:$(SRC_ROOT)/dvpp/%.cpp
  62 + $(XX) $(CFLAGS) -c $<
  63 +
  64 +%.o:$(SRC_ROOT)/%.cu
  65 + @echo "#######################CU_OBJS:$@###############"
  66 + $(NVCC) $(NFLAGS) -o $@ $<
  67 +
  68 +clean:
  69 + rm -f *.o $(TARGET)
0 70 \ No newline at end of file
... ...
src/demo/Makefile 0 → 100644
  1 +# 各项目录
  2 +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib
  3 +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep
  4 +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj
  5 +SRC_DIR:=$(TOP_DIR)/$(MODULE)
  6 +
  7 +# 源文件以及中间目标文件和依赖文件
  8 +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp))
  9 +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS)))
  10 +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS)))
  11 +
  12 +# 自动生成头文件依赖选项
  13 +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
  14 +
  15 +DEFS = -DENABLE_DVPP_INTERFACE
  16 +
  17 +# 最终目标文件
  18 +TARGET:=$(BUILD_DIR)/bin/demo
  19 +
  20 +
  21 +include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/runtime/include
  22 +
  23 +lib_dir=-L/usr/lib \
  24 + -L/usr/local/lib \
  25 + -L/usr/local/Ascend/driver/lib64 \
  26 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/atc/lib64\
  27 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/runtime/lib64 \
  28 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/runtime/lib64/stub \
  29 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/lib64 \
  30 + -L/usr/local/Ascend/driver/lib64/driver
  31 +
  32 +lib=-lacl_dvpp -lascendcl -lmmpa -lglog -lgflags -lpthread -lz -lacl_dvpp_mpi -lruntime -lascendalog -lc_sec -lmsprofiler -lgert -lge_executor -lge_common \
  33 + -lgraph -lascend_protobuf -lprofapi -lerror_manager -lexe_graph -lregister -lplatform
  34 +
  35 +INCLUDE= -I $(TOP_DIR)/interface \
  36 +
  37 +LIBSPATH= -L $(BUILD_DIR)/interface/lib -l:interface.a \
  38 + -L $(BUILD_DIR)/dvpp/lib -l:dvpp.a
  39 +
  40 +CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(include_dir) $(LIBSPATH) $(INCS) $(LIBS) $(lib_dir) $(lib) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl
  41 + # -DUNICODE -D_UNICODE
  42 +
  43 +# 默认最终目标
  44 +.PHONY:all
  45 +all:$(TARGET)
  46 +
  47 +# 生成最终目标
  48 +$(TARGET): $(OBJS) | $(LIB_DIR)
  49 + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m"
  50 + @echo -e "$(CXX) -o $@ $^ $(DEPFLAGS) $(CXXFLAGS) $(MACROS)"
  51 + $(CXX) -o $@ $^ $(DEPFLAGS) $(CXXFLAGS) $(MACROS)
  52 +
  53 +# 若没有lib目录则自动生成
  54 +$(LIB_DIR):
  55 + @mkdir -p $@
  56 +
  57 +# 生成中间目标文件
  58 +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR)
  59 + @echo -e "\e[33m""Building object $@""\e[0m"
  60 + @echo -e "$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<"
  61 + $(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<
  62 +
  63 +# 若没有obj目录则自动生成
  64 +$(OBJ_DIR):
  65 + @mkdir -p $@
  66 +
  67 +# 若没有.dep目录则自动生成
  68 +$(DEP_DIR):
  69 + @mkdir -p $@
  70 +
  71 +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错
  72 +$(DEPS):
  73 +
  74 +# 引入中间目标文件头文件依赖关系
  75 +include $(wildcard $(DEPS))
  76 +
  77 +# 直接删除组件build目录
  78 +.PHONY:clean
  79 +clean:
  80 + @rm -rf $(BUILD_DIR)/$(MODULE)
... ...
src/demo/Makefile.dvpp 0 → 100644
  1 +# 各项目录
  2 +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib
  3 +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep
  4 +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj
  5 +SRC_DIR:=$(TOP_DIR)/$(MODULE)
  6 +
  7 +# 源文件以及中间目标文件和依赖文件
  8 +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp))
  9 +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS)))
  10 +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS)))
  11 +
  12 +# 自动生成头文件依赖选项
  13 +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
  14 +
  15 +DEFS = -DENABLE_DVPP_INTERFACE
  16 +
  17 +# 最终目标文件
  18 +TARGET:=$(BUILD_DIR)/bin/demo
  19 +
  20 +
  21 +include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/runtime/include
  22 +
  23 +lib_dir=-L/usr/lib \
  24 + -L/usr/local/lib \
  25 + -L/usr/local/Ascend/driver/lib64 \
  26 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/atc/lib64\
  27 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/runtime/lib64 \
  28 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/runtime/lib64/stub \
  29 + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/lib64 \
  30 + -L/usr/local/Ascend/driver/lib64/driver
  31 +
  32 +lib=-lacl_dvpp -lascendcl -lmmpa -lglog -lgflags -lpthread -lz -lacl_dvpp_mpi -lruntime -lascendalog -lc_sec -lmsprofiler -lgert -lge_executor -lge_common \
  33 + -lgraph -lascend_protobuf -lprofapi -lerror_manager -lexe_graph -lregister -lplatform
  34 +
  35 +INCLUDE= -I $(TOP_DIR)/interface \
  36 +
  37 +LIBSPATH= -L $(BUILD_DIR)/interface/lib -l:interface.a \
  38 + -L $(BUILD_DIR)/dvpp/lib -l:dvpp.a
  39 +
  40 +CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(include_dir) $(LIBSPATH) $(INCS) $(LIBS) $(lib_dir) $(lib) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl
  41 + # -DUNICODE -D_UNICODE
  42 +
  43 +# 默认最终目标
  44 +.PHONY:all
  45 +all:$(TARGET)
  46 +
  47 +# 生成最终目标
  48 +$(TARGET): $(OBJS) | $(LIB_DIR)
  49 + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m"
  50 + @echo -e "$(CXX) -o $@ $^ $(DEPFLAGS) $(CXXFLAGS) $(MACROS)"
  51 + $(CXX) -o $@ $^ $(DEPFLAGS) $(CXXFLAGS) $(MACROS)
  52 +
  53 +# 若没有lib目录则自动生成
  54 +$(LIB_DIR):
  55 + @mkdir -p $@
  56 +
  57 +# 生成中间目标文件
  58 +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR)
  59 + @echo -e "\e[33m""Building object $@""\e[0m"
  60 + @echo -e "$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<"
  61 + $(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<
  62 +
  63 +# 若没有obj目录则自动生成
  64 +$(OBJ_DIR):
  65 + @mkdir -p $@
  66 +
  67 +# 若没有.dep目录则自动生成
  68 +$(DEP_DIR):
  69 + @mkdir -p $@
  70 +
  71 +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错
  72 +$(DEPS):
  73 +
  74 +# 引入中间目标文件头文件依赖关系
  75 +include $(wildcard $(DEPS))
  76 +
  77 +# 直接删除组件build目录
  78 +.PHONY:clean
  79 +clean:
  80 + @rm -rf $(BUILD_DIR)/$(MODULE)
... ...
src/demo/Makefile.o.nvdec 0 → 100644
  1 +# 各项目录
  2 +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib
  3 +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep
  4 +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj
  5 +SRC_DIR:=$(TOP_DIR)/$(MODULE)
  6 +
  7 +# 源文件以及中间目标文件和依赖文件
  8 +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp))
  9 +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS)))
  10 +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS)))
  11 +
  12 +# 自动生成头文件依赖选项
  13 +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
  14 +
  15 +# 最终目标文件
  16 +TARGET:=/mnt/data/cmhu/FFNvDecoder/bin/lib/demo
  17 +
  18 +
  19 +JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export
  20 +
  21 +INCLUDE= -I $(TOP_DIR)/interface \
  22 + -I $(TOP_DIR)/nvdec \
  23 + -I $(TOP_DIR)/gb28181 \
  24 + -I $(CUDA_ROOT)/include \
  25 + -I $(TOP_DIR)/common/inc \
  26 + -I $(TOP_DIR)/common/UtilNPP \
  27 + -I $(TOP_DIR)/ \
  28 + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \
  29 + -I $(JRTP_ROOT)/jthread/include/jthread
  30 +
  31 +LIBSPATH= -L $(BUILD_DIR)/interface/lib -l:interface.a \
  32 + -L $(BUILD_DIR)/nvdec/lib -l:nvdec.a \
  33 + -L $(BUILD_DIR)/gb28181/lib -l:gb28181.a \
  34 + -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \
  35 + -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \
  36 + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a
  37 +
  38 +CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(LIBSPATH) $(INCS) $(LIBS) $(MACROS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl -Wwrite-strings
  39 + # -DUNICODE -D_UNICODE
  40 +
  41 +# 默认最终目标
  42 +.PHONY:all
  43 +all:$(TARGET)
  44 +
  45 +# 生成最终目标
  46 +$(TARGET): $(OBJS) | $(LIB_DIR)
  47 + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m"
  48 + @echo -e "$(CXX) -o $@ $^ $(DEPFLAGS) $(CXXFLAGS) $(LIBSPATH) $(MACROS)"
  49 + $(CXX) -o $@ $^ $(DEPFLAGS) $(CXXFLAGS) $(LIBSPATH) $(MACROS)
  50 +
  51 +# 若没有lib目录则自动生成
  52 +$(LIB_DIR):
  53 + @mkdir -p $@
  54 +
  55 +# 生成中间目标文件
  56 +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR)
  57 + @echo -e "\e[33m""Building object $@""\e[0m"
  58 + @echo -e "$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<"
  59 + $(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<
  60 +
  61 +# 若没有obj目录则自动生成
  62 +$(OBJ_DIR):
  63 + @mkdir -p $@
  64 +
  65 +# 若没有.dep目录则自动生成
  66 +$(DEP_DIR):
  67 + @mkdir -p $@
  68 +
  69 +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错
  70 +$(DEPS):
  71 +
  72 +# 引入中间目标文件头文件依赖关系
  73 +include $(wildcard $(DEPS))
  74 +
  75 +# 直接删除组件build目录
  76 +.PHONY:clean
  77 +clean:
  78 + @rm -rf $(BUILD_DIR)/$(MODULE)
... ...
src/main.cpp renamed to src/demo/main_dvpp.cpp
1   -#include "FFNvDecoderManager.h"
2 1 #include <iostream>
3   -
4   -#include "cuda_kernels.h"
5   -
6   -#include "NvJpegEncoder.h"
7   -
8 2 #include <pthread.h>
9 3 #include <thread>
10   -
11 4 #include <chrono>
12   -
13 5 #include <unistd.h>
14 6  
15 7 #include "FFSaveImg.h"
... ... @@ -23,7 +15,8 @@
23 15 #include "arpa/inet.h"
24 16 #endif
25 17  
26   -#include "utiltools.hpp"
  18 +#include "../interface/FFNvDecoderManager.h"
  19 +#include "../interface/utiltools.hpp"
27 20  
28 21 #include "curl/curl.h"
29 22  
... ... @@ -89,75 +82,11 @@ unsigned char *pHwRgb[2] = {nullptr, nullptr};
89 82 int sum1 = 0;
90 83 int sum2 = 0;
91 84  
92   -cudaStream_t stream[2];
93 85  
94 86 string data_home = "/mnt/data/cmhu/tmp/";
95 87  
96 88  
97   -#define checkCudaErrors(S) do {CUresult status; \
98   - status = S; \
99   - if (status != CUDA_SUCCESS ) std::cout << __LINE__ <<" checkCudaErrors - status = " << status << std::endl; \
100   - } while (false)
101   -
102   -
103   -static void gpu_helper(int gpuid)
104   -{
105   - cudaSetDevice(gpuid);
106   -
107   - // int *dn;
108   - // cudaMalloc((void **)&dn, 1 * sizeof(int));
109 89  
110   - size_t free_byte;
111   - size_t total_byte;
112   -
113   - CUresult cuda_status = cuMemGetInfo(&free_byte, &total_byte);
114   -
115   - const char *pStr = nullptr;
116   - if (CUDA_SUCCESS != cuda_status) {
117   - cuGetErrorString(cuda_status, &pStr);
118   - printf("Error: cudaMemGetInfo fails, %s \n", pStr);
119   - return;
120   - }
121   -
122   - double free_db = (double)free_byte;
123   - double total_db = (double)total_byte;
124   - double used_db_1 = (total_db - free_db) / 1024.0 / 1024.0;
125   -
126   - std::cout <<"显存已使用 " << used_db_1 << " MB\n";
127   -
128   - // cudaFree(dn);
129   -}
130   -
131   -int CheckCUDAProperty( int devId )
132   -{
133   - cuInit(0);
134   -
135   - CUdevice dev = devId;
136   - size_t memSize = 0;
137   - char devName[256] = {0};
138   - int major = 0, minor = 0;
139   - CUresult rlt = CUDA_SUCCESS;
140   -
141   - rlt = cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, dev);
142   - checkCudaErrors( rlt );
143   -
144   - rlt = cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, dev);
145   - checkCudaErrors( rlt );
146   -
147   - rlt = cuDeviceGetName( devName, sizeof( devName ), dev );
148   - checkCudaErrors( rlt );
149   -
150   - printf( "Using GPU Device %d: %s has SM %d.%d compute capability\n",
151   - dev, devName, major, minor );
152   -
153   - rlt = cuDeviceTotalMem( &memSize, dev );
154   - checkCudaErrors( rlt );
155   -
156   - printf( "Total amount of global memory: %4.4f MB\n",
157   - (float)memSize / ( 1024 * 1024 ) );
158   -
159   - return 0;
160   -}
161 90  
162 91 static long get_cur_time_ms() {
163 92 chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro
... ... @@ -168,87 +97,15 @@ static long get_cur_time_ms() {
168 97 /**
169 98 * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况
170 99 * */
171   -void postDecoded(const void * userPtr, AVFrame * gpuFrame){
172   -
173   - // long first_time = get_cur_time_ms();
174   - // long second_time = 0;
175   - // int a = 1;
176   - // while(true){
177   - // a = a * 99;
178   - // if(a > 1000000){
179   - // a = 1;
180   - // }
181   - // second_time = get_cur_time_ms();
182   - // if(second_time - first_time > 100){
183   - // break;
184   - // }
185   - // }
186   - // return ;
187   -
188   - // std::this_thread::sleep_for(std::chrono::milliseconds(100));
189   -
  100 +void postDecoded(const void * userPtr, DeviceRgbMemory* devFrame){
190 101 AbstractDecoder* decoder = (AbstractDecoder*)userPtr;
191 102 if (decoder!= nullptr)
192 103 {
193   - // cout << "decode name: " << decoder->getName() << endl;
194   -
195   - // const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format);
196   - // cout << "pixfmt: " << gpu_pixfmt << endl;
197   - // cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
198   - // cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl;
  104 + }
199 105  
200   - int sum = sum1;
201   - if (decoder->getName() == "dec0")
202   - {
203   - sum1 ++ ;
204   - sum = sum1;
205   -
206   - if (gpuFrame->format == AV_PIX_FMT_CUDA)
207   - {
208   - // cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl;
209   - cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
210   - cudaError_t cudaStatus;
211   - if(pHwRgb[0] == nullptr){
212   - // cudaStreamCreate(&stream[0]);
213   - cuda_common::setColorSpace( ITU_709, 0 );
214   - cudaStatus = cudaMalloc((void **)&pHwRgb[0], 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
215   - }
216   - cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb[0], gpuFrame->width, gpuFrame->height);
217   - cudaDeviceSynchronize();
218   - if (cudaStatus != cudaSuccess) {
219   - cout << "CUDAToBGR failed !!!" << endl;
220   - return;
221   - }
222   -
223   - string path = data_home + decoder->getName() + ".jpg";
224   - saveJpeg(path.c_str(), pHwRgb[0], gpuFrame->width, gpuFrame->height, stream[0]); // 验证 CUDAToRGB
225   - }
226   - } else if (decoder->getName() == "dec2")
227   - {
228   - sum2 ++ ;
229   - sum = sum2;
230   -
231   - if (gpuFrame->format == AV_PIX_FMT_CUDA)
232   - {
233   - // cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl;
234   - cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
235   - cudaError_t cudaStatus;
236   - if(pHwRgb[1] == nullptr){
237   - // cudaStreamCreate(&stream[1]);
238   - cuda_common::setColorSpace( ITU_709, 0 );
239   - cudaStatus = cudaMalloc((void **)&pHwRgb[1], 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
240   - }
241   - cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb[1], gpuFrame->width, gpuFrame->height);
242   - cudaDeviceSynchronize();
243   - if (cudaStatus != cudaSuccess) {
244   - cout << "CUDAToBGR failed !!!" << endl;
245   - return;
246   - }
247   -
248   - string path = data_home + decoder->getName() + ".jpg";
249   - saveJpeg(path.c_str(), pHwRgb[1], gpuFrame->width, gpuFrame->height, stream[1]); // 验证 CUDAToRGB
250   - }
251   - }
  106 + if(devFrame){
  107 + delete devFrame;
  108 + devFrame = nullptr;
252 109 }
253 110 }
254 111  
... ... @@ -262,9 +119,8 @@ int count_std = 100;
262 119 static int sum = 0;
263 120 unsigned char *pHwData = nullptr;
264 121  
265   -void postDecoded0(const void * userPtr, AVFrame * gpuFrame){
266   -
267   - std::this_thread::sleep_for(std::chrono::milliseconds(100));
  122 +void postDecoded0(const void * userPtr, DeviceRgbMemory* devFrame){
  123 + // std::this_thread::sleep_for(std::chrono::milliseconds(30000));
268 124  
269 125 AbstractDecoder* decoder = (AbstractDecoder*)userPtr;
270 126 if (decoder!= nullptr)
... ... @@ -286,32 +142,12 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){
286 142 // long time_using = end_time - start_time;
287 143 // double time_per_frame = double(time_using)/count_std ;
288 144 // cout << count_std << "帧用时:" << time_using << "ms 每帧用时:" << time_per_frame << "ms" << endl;
289   - cout << decoder->getName() << " keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
  145 + cout << decoder->getName() << " keyframe: " << devFrame->isKeyFrame() << " width: " << devFrame->getWidth() << " height: "<< devFrame->getHeight() << endl;
290 146 // cout << gpuFrame->pts << endl;
291 147  
292 148 count_flag = false;
293 149 }
294 150 // cout << "帧数:" << sum << endl;
295   -
296   - if (gpuFrame->format == AV_PIX_FMT_CUDA)
297   - {
298   - cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
299   - // cout << "gpu id : " << decoder->m_cfg.gpuid.c_str() << endl;
300   - cudaError_t cudaStatus;
301   - if(pHwData == nullptr){
302   - cuda_common::setColorSpace( ITU_709, 0 );
303   - cudaStatus = cudaMalloc((void **)&pHwData, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
304   - }
305   - cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwData, gpuFrame->width, gpuFrame->height);
306   - cudaDeviceSynchronize();
307   - if (cudaStatus != cudaSuccess) {
308   - cout << "CUDAToBGR failed !!!" << endl;
309   - return;
310   - }
311   -
312   - string path = data_home + decoder->getName() + ".jpg";
313   - saveJpeg(path.c_str(), pHwData, gpuFrame->width, gpuFrame->height, nullptr); // 验证 CUDAToRGB
314   - }
315 151 }
316 152 }
317 153 }
... ... @@ -514,7 +350,9 @@ bool decode_request_stream_cbk(const char* deviceId){
514 350 // string test_uri = "/home/cmhu/data/output_1920x1080.mp4";
515 351 // string test_uri = "rtsp://176.10.0.2:8554/stream";
516 352 // string test_uri = "/mnt/f/fiss/test_data/h265.mp4";
517   -string test_uri = "rtsp://192.168.10.4:8554/street";
  353 +// string test_uri = "rtsp://176.10.0.4:8554/stream";
  354 +// string test_uri = "rtsp://admin:admin@123456@192.168.60.176:554/cam/realmonitor?channel=1&subtype=0";
  355 +string test_uri = "/home/huchunming/data/woyikewangh265.mp4";
518 356  
519 357 void createDecode(int index, const char* gpu_id){
520 358 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
... ... @@ -575,6 +413,29 @@ void createGB28181Decode(char* devid, char* gpu_id, int port){
575 413 pDecManager->startDecodeByName(config.name);
576 414 }
577 415  
  416 +void createDvppDecoder(int index, char* devId, int channelId){
  417 + FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
  418 + MgrDecConfig config;
  419 + config.name = "dec" + to_string(index);
  420 + config.cfg.uri = test_uri;
  421 + config.cfg.post_decoded_cbk = postDecoded;
  422 + config.cfg.decode_finished_cbk = decode_finished_cbk;
  423 + config.cfg.force_tcp = true;
  424 + config.dec_type = DECODER_TYPE_DVPP;
  425 +
  426 + config.cfg.gpuid = devId;
  427 +
  428 + AbstractDecoder* decoder = pDecManager->createDecoder(config);
  429 + if (!decoder)
  430 + {
  431 + cout << "创建解码器失败" << endl;
  432 + return ;
  433 + }
  434 + pDecManager->setPostDecArg(config.name, decoder);
  435 + pDecManager->setFinishedDecArg(config.name, decoder);
  436 + pDecManager->startDecodeByName(config.name);
  437 +}
  438 +
578 439 void logFF(void *, int level, const char *fmt, va_list ap)
579 440 {
580 441 vfprintf(stdout, fmt, ap);
... ... @@ -583,7 +444,7 @@ void logFF(void *, int level, const char *fmt, va_list ap)
583 444  
584 445 int main(int argc, char* argv[]){
585 446  
586   - test_uri = argv[1];
  447 + // test_uri = argv[1];
587 448 char* gpuid = argv[2];
588 449 int port = atoi(argv[3]);
589 450 char* devId = argv[4];
... ... @@ -591,7 +452,7 @@ int main(int argc, char* argv[]){
591 452  
592 453 // av_log_set_callback(&logFF);
593 454  
594   - CheckCUDAProperty(atoi(gpuid));
  455 + // CheckCUDAProperty(atoi(gpuid));
595 456  
596 457 pthread_t m_decode_thread;
597 458 pthread_create(&m_decode_thread,0,
... ... @@ -644,6 +505,11 @@ int main(int argc, char* argv[]){
644 505 createGB28181Decode(devId, gpuid, port);
645 506 i++;
646 507 break;
  508 + case 'd':
  509 + case 'D':
  510 + createDvppDecoder(i, gpuid, 0);
  511 + i++;
  512 + break;
647 513 case 'r':
648 514 case 'R':
649 515 pDecManager->resumeDecoder("dec0");
... ...
src/demo/main_nvdec.cpp1 0 → 100644
  1 +#include "FFNvDecoderManager.h"
  2 +#include <iostream>
  3 +
  4 +// #include "cuda_kernels.h"
  5 +// #include "NvJpegEncoder.h"
  6 +
  7 +#include <pthread.h>
  8 +#include <thread>
  9 +
  10 +#include <chrono>
  11 +
  12 +#include <unistd.h>
  13 +
  14 +
  15 +#ifdef _WIN32
  16 +#include "Winsock2.h"
  17 +#pragma comment(lib, "ws2_32.lib")
  18 +#endif
  19 +
  20 +#ifdef __linux__
  21 +#include "arpa/inet.h"
  22 +#endif
  23 +
  24 +#include "utiltools.hpp"
  25 +
  26 +#define MIN_RTP_PORT 10000
  27 +#define MAX_RTP_PORT 60000
  28 +
  29 +// ȡ MIN_RTP_PORT(10000)~MAX_RTP_PORT(60000)֮�������˿�(ż���������������˿ڿ���)
  30 +int allocRtpPort() {
  31 +
  32 + static int s_rtpPort = MIN_RTP_PORT;
  33 + if (MIN_RTP_PORT == s_rtpPort)
  34 + {
  35 + srand((unsigned int)time(NULL));
  36 + s_rtpPort = MIN_RTP_PORT + (rand() % MIN_RTP_PORT);
  37 + }
  38 +
  39 + if (s_rtpPort % 2)
  40 + ++s_rtpPort;
  41 +
  42 + while (true)
  43 + {
  44 + s_rtpPort += 2;
  45 + s_rtpPort = s_rtpPort >= MAX_RTP_PORT ? MIN_RTP_PORT : s_rtpPort;
  46 +
  47 + int i = 0;
  48 + for (; i < 2; i++)
  49 + {
  50 + sockaddr_in sRecvAddr;
  51 + int s = socket(AF_INET, SOCK_DGRAM, 0);
  52 +
  53 + sRecvAddr.sin_family = AF_INET;
  54 + sRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  55 + sRecvAddr.sin_port = htons(s_rtpPort + i);
  56 +
  57 + int nResult = bind(s, (sockaddr *)&sRecvAddr, sizeof(sRecvAddr));
  58 + if (nResult != 0)
  59 + {
  60 + break;
  61 + }
  62 +
  63 + nResult = close(s);
  64 + if (nResult != 0)
  65 + {
  66 + printf("closesocket failed:%d\n", nResult);
  67 + break;
  68 + }
  69 + }
  70 +
  71 + if (i == 2)
  72 + break;
  73 + }
  74 +
  75 + return s_rtpPort;
  76 +}
  77 +
  78 +
  79 +
  80 +
  81 +
  82 +unsigned char *pHwRgb[2] = {nullptr, nullptr};
  83 +
  84 +int sum1 = 0;
  85 +int sum2 = 0;
  86 +
  87 +// cudaStream_t stream[2];
  88 +
  89 +string data_home = "/mnt/data/cmhu/tmp/";
  90 +
  91 +
  92 +// #define checkCudaErrors(S) do {CUresult status; \
  93 +// status = S; \
  94 +// if (status != CUDA_SUCCESS ) std::cout << __LINE__ <<" checkCudaErrors - status = " << status << std::endl; \
  95 +// } while (false)
  96 +
  97 +
  98 +// static void gpu_helper(int gpuid)
  99 +// {
  100 +// cudaSetDevice(gpuid);
  101 +
  102 +// // int *dn;
  103 +// // cudaMalloc((void **)&dn, 1 * sizeof(int));
  104 +
  105 +// size_t free_byte;
  106 +// size_t total_byte;
  107 +
  108 +// CUresult cuda_status = cuMemGetInfo(&free_byte, &total_byte);
  109 +
  110 +// const char *pStr = nullptr;
  111 +// if (CUDA_SUCCESS != cuda_status) {
  112 +// cuGetErrorString(cuda_status, &pStr);
  113 +// printf("Error: cudaMemGetInfo fails, %s \n", pStr);
  114 +// return;
  115 +// }
  116 +
  117 +// double free_db = (double)free_byte;
  118 +// double total_db = (double)total_byte;
  119 +// double used_db_1 = (total_db - free_db) / 1024.0 / 1024.0;
  120 +
  121 +// std::cout <<"显存已使用 " << used_db_1 << " MB\n";
  122 +
  123 +// // cudaFree(dn);
  124 +// }
  125 +
  126 +// int CheckCUDAProperty( int devId )
  127 +// {
  128 +// cuInit(0);
  129 +
  130 +// CUdevice dev = devId;
  131 +// size_t memSize = 0;
  132 +// char devName[256] = {0};
  133 +// int major = 0, minor = 0;
  134 +// CUresult rlt = CUDA_SUCCESS;
  135 +
  136 +// rlt = cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, dev);
  137 +// checkCudaErrors( rlt );
  138 +
  139 +// rlt = cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, dev);
  140 +// checkCudaErrors( rlt );
  141 +
  142 +// rlt = cuDeviceGetName( devName, sizeof( devName ), dev );
  143 +// checkCudaErrors( rlt );
  144 +
  145 +// printf( "Using GPU Device %d: %s has SM %d.%d compute capability\n",
  146 +// dev, devName, major, minor );
  147 +
  148 +// rlt = cuDeviceTotalMem( &memSize, dev );
  149 +// checkCudaErrors( rlt );
  150 +
  151 +// printf( "Total amount of global memory: %4.4f MB\n",
  152 +// (float)memSize / ( 1024 * 1024 ) );
  153 +
  154 +// return 0;
  155 +// }
  156 +
  157 +/**
  158 + * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况
  159 + * */
  160 +static long lastpts = 0;
  161 +void postDecoded(const void * userPtr, DeviceRgbMemory * gpuFrame){
  162 + AbstractDecoder* decoder = (AbstractDecoder*)userPtr;
  163 + if (decoder!= nullptr)
  164 + {
  165 + long curpts = UtilTools::get_cur_time_ms();
  166 + cout << decoder->getName() << " " << gpuFrame->getWidth() << "x" << gpuFrame->getHeight() << " " << curpts - lastpts << endl;
  167 + lastpts = curpts;
  168 + delete gpuFrame;
  169 + gpuFrame = nullptr;
  170 +
  171 + // const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format);
  172 + // cout << "pixfmt: " << gpu_pixfmt << endl;
  173 + // cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
  174 + // cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl;
  175 +
  176 + // int sum = sum1;
  177 + // if (decoder->getName() == "dec0")
  178 + // {
  179 + // sum1 ++ ;
  180 + // sum = sum1;
  181 +
  182 + // if (gpuFrame->format == AV_PIX_FMT_CUDA)
  183 + // {
  184 + // // cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl;
  185 + // cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
  186 + // cudaError_t cudaStatus;
  187 + // if(pHwRgb[0] == nullptr){
  188 + // // cudaStreamCreate(&stream[0]);
  189 + // cuda_common::setColorSpace( ITU_709, 0 );
  190 + // cudaStatus = cudaMalloc((void **)&pHwRgb[0], 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
  191 + // }
  192 + // cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb[0], gpuFrame->width, gpuFrame->height);
  193 + // cudaDeviceSynchronize();
  194 + // if (cudaStatus != cudaSuccess) {
  195 + // cout << "CUDAToBGR failed !!!" << endl;
  196 + // return;
  197 + // }
  198 +
  199 + // string path = data_home + decoder->getName() + ".jpg";
  200 + // saveJpeg(path.c_str(), pHwRgb[0], gpuFrame->width, gpuFrame->height, stream[0]); // 验证 CUDAToRGB
  201 + // }
  202 + // } else if (decoder->getName() == "dec2")
  203 + // {
  204 + // sum2 ++ ;
  205 + // sum = sum2;
  206 +
  207 + // if (gpuFrame->format == AV_PIX_FMT_CUDA)
  208 + // {
  209 + // // cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl;
  210 + // cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
  211 + // cudaError_t cudaStatus;
  212 + // if(pHwRgb[1] == nullptr){
  213 + // // cudaStreamCreate(&stream[1]);
  214 + // cuda_common::setColorSpace( ITU_709, 0 );
  215 + // cudaStatus = cudaMalloc((void **)&pHwRgb[1], 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
  216 + // }
  217 + // cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb[1], gpuFrame->width, gpuFrame->height);
  218 + // cudaDeviceSynchronize();
  219 + // if (cudaStatus != cudaSuccess) {
  220 + // cout << "CUDAToBGR failed !!!" << endl;
  221 + // return;
  222 + // }
  223 +
  224 + // string path = data_home + decoder->getName() + ".jpg";
  225 + // saveJpeg(path.c_str(), pHwRgb[1], gpuFrame->width, gpuFrame->height, stream[1]); // 验证 CUDAToRGB
  226 + // }
  227 + // }
  228 + }
  229 +}
  230 +
  231 +long start_time = 0;
  232 +long end_time = 0;
  233 +bool count_flag = false;
  234 +int count = 0;
  235 +int count_std = 100;
  236 +
  237 +
  238 +static int sum = 0;
  239 +unsigned char *pHwData = nullptr;
  240 +
  241 +void postDecoded0(const void * userPtr, DeviceRgbMemory* gpuFrame){
  242 + // std::this_thread::sleep_for(std::chrono::milliseconds(30000));
  243 +
  244 + AbstractDecoder* decoder = (AbstractDecoder*)userPtr;
  245 + if (decoder!= nullptr)
  246 + {
  247 + // cout << "decode name: " << decoder->getName() << endl;
  248 + // if (decoder->getName() == "dec")
  249 + // {
  250 + // if (! count_flag)
  251 + // {
  252 + // count_flag = true;
  253 + // count = 0;
  254 + // end_time = start_time = UtilTools::get_cur_time_ms();
  255 + // }
  256 + // count++;
  257 + // sum ++ ;
  258 + // if (count >= count_std)
  259 + // {
  260 + // // end_time = UtilTools::get_cur_time_ms();
  261 + // // long time_using = end_time - start_time;
  262 + // // double time_per_frame = double(time_using)/count_std ;
  263 + // // cout << count_std << "帧用时:" << time_using << "ms 每帧用时:" << time_per_frame << "ms" << endl;
  264 + // cout << decoder->getName() << " keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
  265 + // // cout << gpuFrame->pts << endl;
  266 +
  267 + // count_flag = false;
  268 + // }
  269 + // // cout << "帧数:" << sum << endl;
  270 +
  271 + // if (gpuFrame->format == AV_PIX_FMT_CUDA)
  272 + // {
  273 + // cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
  274 + // // cout << "gpu id : " << decoder->m_cfg.gpuid.c_str() << endl;
  275 + // cudaError_t cudaStatus;
  276 + // if(pHwData == nullptr){
  277 + // cuda_common::setColorSpace( ITU_709, 0 );
  278 + // cudaStatus = cudaMalloc((void **)&pHwData, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
  279 + // }
  280 + // cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwData, gpuFrame->width, gpuFrame->height);
  281 + // cudaDeviceSynchronize();
  282 + // if (cudaStatus != cudaSuccess) {
  283 + // cout << "CUDAToBGR failed !!!" << endl;
  284 + // return;
  285 + // }
  286 +
  287 + // string path = data_home + decoder->getName() + ".jpg";
  288 + // saveJpeg(path.c_str(), pHwData, gpuFrame->width, gpuFrame->height, nullptr); // 验证 CUDAToRGB
  289 + // }
  290 + // }
  291 + }
  292 +}
  293 +
  294 +void decode_finished_cbk(const void* userPtr){
  295 + cout << "当前时间戳: " << UtilTools::get_cur_time_ms() << endl;
  296 +}
  297 +
  298 +bool decode_request_stream_cbk(const char* deviceId){
  299 + cout << "需在此请求流" << endl;
  300 + return true;
  301 +}
  302 +
  303 +// string test_uri = "rtmp://192.168.10.56:1935/objecteye/1";
  304 +// string test_uri = "/home/cmhu/data/output_800x480.mp4";
  305 +// string test_uri = "/home/cmhu/data/output_1920x1080.mp4";
  306 +// string test_uri = "rtsp://176.10.0.2:8554/stream";
  307 +// string test_uri = "/mnt/f/fiss/test_data/h265.mp4";
  308 +string test_uri = "rtsp://176.10.0.4:8554/stream";
  309 +
  310 +void createDecode(int index, const char* gpu_id){
  311 + FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
  312 + MgrDecConfig config;
  313 + config.name = "dec" + to_string(index);
  314 + config.cfg.uri = test_uri;
  315 + config.cfg.post_decoded_cbk = postDecoded;
  316 + config.cfg.decode_finished_cbk = decode_finished_cbk;
  317 + config.cfg.force_tcp = true;
  318 + config.dec_type = DECODER_TYPE_FFMPEG;
  319 +
  320 + config.cfg.gpuid = gpu_id;
  321 + // if (index % 2 == 0)
  322 + // {
  323 + // config.cfg.gpuid = "0";
  324 + // }
  325 + // else
  326 + // {
  327 + // config.cfg.gpuid = "0";
  328 + // }
  329 +
  330 + AbstractDecoder* decoder = pDecManager->createDecoder(config);
  331 + if (!decoder)
  332 + {
  333 + return ;
  334 + }
  335 + pDecManager->setPostDecArg(config.name, decoder);
  336 + pDecManager->setFinishedDecArg(config.name, decoder);
  337 + pDecManager->startDecodeByName(config.name);
  338 +}
  339 +
  340 +void createGB28181Decode(int index, char* gpu_id, int port){
  341 + FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
  342 + MgrDecConfig config;
  343 + config.name = "dec" + to_string(index);
  344 + config.cfg.uri = config.name;
  345 + config.cfg.post_decoded_cbk = postDecoded;
  346 + config.cfg.decode_finished_cbk = decode_finished_cbk;
  347 + config.cfg.request_stream_cbk = decode_request_stream_cbk;
  348 + config.cfg.force_tcp = true;
  349 +
  350 + config.dec_type = DECODER_TYPE_GB28181;
  351 + config.cfg.port = port;//allocRtpPort();
  352 +
  353 + config.cfg.gpuid = gpu_id;
  354 +
  355 + AbstractDecoder* decoder = pDecManager->createDecoder(config);
  356 + if (!decoder)
  357 + {
  358 + return ;
  359 + }
  360 + pDecManager->setPostDecArg(config.name, decoder);
  361 + pDecManager->setFinishedDecArg(config.name, decoder);
  362 + pDecManager->startDecodeByName(config.name);
  363 +}
  364 +
  365 +void logFF(void *, int level, const char *fmt, va_list ap)
  366 +{
  367 + vfprintf(stdout, fmt, ap);
  368 +}
  369 +
  370 +
  371 +int main(int argc, char* argv[]){
  372 +
  373 + test_uri = "rtsp://admin:admin@123456@192.168.60.176:554/cam/realmonitor?channel=1&subtype=0";//argv[1];
  374 + char* gpuid = argv[2];
  375 + int port = atoi(argv[3]);
  376 + cout << test_uri << " gpu_id:" << gpuid << " port:" << port << endl;
  377 +
  378 + // av_log_set_callback(&logFF);
  379 +
  380 + // CheckCUDAProperty(atoi(gpuid));
  381 +
  382 + pthread_t m_decode_thread;
  383 + pthread_create(&m_decode_thread,0,
  384 + [](void* arg)
  385 + {
  386 + // cudaSetDevice(atoi(gpuid));
  387 + while (true)
  388 + {
  389 + std::this_thread::sleep_for(std::chrono::minutes(1));
  390 + FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
  391 + int count = pDecManager->count();
  392 + cout << "当前时间:" << UtilTools::get_cur_time_ms() << " 当前运行路数: " << pDecManager->count() << endl;
  393 + }
  394 +
  395 + return (void*)0;
  396 + }
  397 + ,nullptr);
  398 +
  399 +
  400 + FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
  401 + int i = 0;
  402 +
  403 + while (true)
  404 + {
  405 + int ch = getchar();
  406 + if (ch == 'q')
  407 + {
  408 + break;
  409 + }
  410 +
  411 + switch (ch)
  412 + {
  413 + case 'f':
  414 + case 'F':
  415 + createDecode(i, gpuid);
  416 + i++;
  417 + break;
  418 + case 'g':
  419 + case 'G':
  420 + createGB28181Decode(i, gpuid, port);
  421 + i++;
  422 + break;
  423 + case 'r':
  424 + case 'R':
  425 + pDecManager->resumeDecoder("dec0");
  426 + break;
  427 + case 'p':
  428 + case 'P':
  429 + pDecManager->pauseDecoder("dec0");
  430 + break;
  431 +
  432 + case 'c':
  433 + case 'C':
  434 + i--;
  435 + pDecManager->closeDecoderByName("dec" + to_string(i));
  436 + break;
  437 +
  438 + case 'i':
  439 + case 'I':
  440 + {
  441 + int w,h;
  442 + pDecManager->getResolution("dec0", w,h);
  443 + printf( "%s : %dx%d\n", "dec0" , w,h );
  444 + }
  445 + break;
  446 +
  447 + default:
  448 + break;
  449 + }
  450 +
  451 + /* code */
  452 + }
  453 +
  454 + cout << "总共帧数:" << sum << endl;
  455 + pDecManager->closeAllDecoder();
  456 +}
0 457 \ No newline at end of file
... ...
src/dvpp/CircularQueue.hpp 0 → 100644
  1 +#ifndef __CIRCULAR_QUEUE_HPP__
  2 +#define __CIRCULAR_QUEUE_HPP__
  3 +
  4 +#include <iostream>
  5 +#include <atomic>
  6 +#include <vector>
  7 +#include <mutex>
  8 +
  9 +using namespace std;
  10 +
  11 +
  12 +// 循环队列
  13 +template <typename T>
  14 +class CircularQueue
  15 +{
  16 +private:
  17 + /* data */
  18 +public:
  19 + CircularQueue();
  20 + ~CircularQueue();
  21 +
  22 + bool init(vector<T> data);
  23 + T getTail();
  24 + void addTail();
  25 + T deQueue();
  26 + T getHead();
  27 + void addHead();
  28 + void clearQueue();
  29 +
  30 + int length();
  31 + bool isEmpty();
  32 +
  33 +private:
  34 + vector<T> base;
  35 + atomic<int> front;
  36 + atomic<int> rear;
  37 + mutex m_mutex;
  38 + int max_size;
  39 +};
  40 +
  41 +
  42 +template <typename T>
  43 +CircularQueue<T>::CircularQueue()
  44 +{
  45 + front = rear = 0;//头指针和尾指针置为零,队列为空
  46 +}
  47 +
  48 +template <typename T>
  49 +CircularQueue<T>::~CircularQueue()
  50 +{
  51 + base.clear();
  52 + rear = front = 0;
  53 +}
  54 +
  55 +template <typename T>
  56 +bool CircularQueue<T>::init(vector<T> data){
  57 + base = data;
  58 + front = rear = 0;//头指针和尾指针置为零,队列为空
  59 + max_size = data.size();
  60 +
  61 + return true;
  62 +}
  63 +
  64 +//循环队列的入队
  65 +template <typename T>
  66 +T CircularQueue<T>::getTail()
  67 +{
  68 + std::lock_guard<std::mutex> l(m_mutex);
  69 + //插入一个元素e为Q的新的队尾元素
  70 + if ((rear + 1) % max_size == front)
  71 + return nullptr;//队满
  72 + return base[rear];//获取队尾元素
  73 +}
  74 +
  75 +// 将队尾元素添加到队列中
  76 +template <typename T>
  77 +void CircularQueue<T>::addTail()
  78 +{
  79 + std::lock_guard<std::mutex> l(m_mutex);
  80 + rear = (rear + 1) % max_size;//队尾指针加1
  81 +}
  82 +
  83 +//循环队列的出队
  84 +template <typename T>
  85 +T CircularQueue<T>::deQueue()
  86 +{
  87 + std::lock_guard<std::mutex> l(m_mutex);
  88 + //删除Q的队头元素,用e返回其值
  89 + if (front == rear)
  90 + return nullptr;//队空
  91 + T e = base[front];//保存队头元素
  92 + front = (front + 1) % max_size;//队头指针加1
  93 + return e;
  94 +}
  95 +
  96 +//取循环队列的队头元素
  97 +template <typename T>
  98 +T CircularQueue<T>::getHead()
  99 +{
  100 + std::lock_guard<std::mutex> l(m_mutex);
  101 + //返回Q的队头元素,不修改队头指针
  102 + if (front == rear)
  103 + return nullptr;//队列为空,取元素失败
  104 + return base[front];
  105 +}
  106 +
  107 +template <typename T>
  108 +void CircularQueue<T>::addHead()
  109 +{
  110 + std::lock_guard<std::mutex> l(m_mutex);
  111 + front = (front + 1) % max_size;//队头指针加1
  112 +}
  113 +
  114 +template <typename T>
  115 +int CircularQueue<T>::length()
  116 +{
  117 + std::lock_guard<std::mutex> l(m_mutex);
  118 + return (rear - front + max_size) % max_size;
  119 +}
  120 +
  121 +template <typename T>
  122 +bool CircularQueue<T>::isEmpty()
  123 +{
  124 + std::lock_guard<std::mutex> l(m_mutex);
  125 + if (front == rear)
  126 + return true;
  127 +
  128 + return false;
  129 +}
  130 +
  131 +template <typename T>
  132 +void CircularQueue<T>::clearQueue()
  133 +{
  134 + std::lock_guard<std::mutex> l(m_mutex);
  135 + rear = front = 0;
  136 +}
  137 +
  138 +#endif
0 139 \ No newline at end of file
... ...
src/dvpp/DvppDec.cpp 0 → 100644
  1 +#include "DvppDec.h"
  2 +#include "DvppSourceManager.h"
  3 +
  4 +struct Vdec_CallBack_UserData {
  5 + uint64_t frameId;
  6 + long startTime;
  7 + long sendTime;
  8 + // void* vdecOutputBuf;
  9 + DvppDec* self;
  10 + shared_ptr<MemNode> inBufNode;
  11 + Vdec_CallBack_UserData() {
  12 + frameId = 0;
  13 + }
  14 +};
  15 +
  16 +static const int g_pkt_size = 1024 * 1024;
  17 +
  18 + DvppDec::DvppDec(){
  19 + m_decode_thread = 0;
  20 + }
  21 +
  22 + DvppDec::~DvppDec(){
  23 + releaseResource();
  24 + }
  25 +
  26 + bool DvppDec::init_vdpp(DvppDecConfig cfg){
  27 +
  28 + m_dec_name = cfg.dec_name;
  29 +
  30 + LOG_INFO("[{}]- Init device start...", m_dec_name);
  31 +
  32 + m_dvpp_deviceId = atoi(cfg.dev_id.c_str());
  33 +
  34 + if(cfg.codec_id == 0){
  35 + // 66:Baseline,77:Main,>=100:High
  36 + if(cfg.profile == 77){
  37 + enType = H264_MAIN_LEVEL;
  38 + }else if(cfg.profile < 77){
  39 + enType = H264_BASELINE_LEVEL;
  40 + }else{
  41 + enType = H264_HIGH_LEVEL;
  42 + }
  43 + }else if(cfg.codec_id == 1){
  44 + // h265只有main
  45 + enType = H265_MAIN_LEVEL;
  46 + }else {
  47 + LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name);
  48 + return false;
  49 + }
  50 +
  51 + post_decoded_cbk = cfg.post_decoded_cbk;
  52 + m_pktQueueptr = cfg.pktQueueptr;
  53 +
  54 + // DvppSourceManager 创建时包含 aclInit,析构时包含 aclFinalize
  55 + DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance();
  56 + m_context = pSrcMgr->getContext(m_dvpp_deviceId);
  57 + m_dvpp_channel = pSrcMgr->getChannel(m_dvpp_deviceId);
  58 + if(m_dvpp_channel < 0){
  59 + LOG_ERROR("[{}]-该设备channel已经用完了!", m_dec_name);
  60 + return false;
  61 + }
  62 +
  63 + do
  64 + {
  65 + CHECK_AND_BREAK(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed !");
  66 +
  67 + int ret = picConverter.init(m_context, m_dec_name);
  68 + if(ret != ACL_ERROR_NONE){
  69 + LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret);
  70 + break;
  71 + }
  72 +
  73 + // queue_size 最小应大于16,否则关键帧之间距离太远的时候会导致回调函数与循环队列卡死
  74 + for (size_t i = 0; i < 20; i++){
  75 + void *vdecInputbuf = nullptr;
  76 + ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size);
  77 + if(ret != ACL_ERROR_NONE){
  78 + LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret);
  79 + // 析构函数中有对channel 的补救性释放,所以这里可以直接return
  80 + return false;;
  81 + }
  82 + m_vec_vdec.push_back(vdecInputbuf);
  83 + }
  84 +
  85 + if(!m_vdecQueue.init(m_vec_vdec)){
  86 + break;
  87 + }
  88 +
  89 + m_vdec_out_size = cfg.width * cfg.height * 3 / 2;
  90 +
  91 + LOG_INFO("[{}]- init vdpp success! device:{} channel:{}", m_dec_name, m_dvpp_deviceId, m_dvpp_channel);
  92 + return true;
  93 +
  94 + } while (0);
  95 +
  96 + LOG_INFO("[{}]- init vdpp failed!", m_dec_name);
  97 + // 初始化失败,释放channel
  98 + pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel);
  99 + return false;
  100 +}
  101 +
  102 +bool DvppDec::start(){
  103 + m_bRunning = true;
  104 +
  105 + pthread_create(&m_decode_thread,0,
  106 + [](void* arg)
  107 + {
  108 + DvppDec* a=(DvppDec*)arg;
  109 + a->decode_thread();
  110 + return (void*)0;
  111 + }
  112 + ,this);
  113 +
  114 + return true;
  115 +}
  116 +
  117 +static void *ReportThd(void *arg)
  118 +{
  119 + DvppDec *self = (DvppDec *)arg;
  120 + if(nullptr != self){
  121 + self->doProcessReport();
  122 + }
  123 + return (void *)0;
  124 +}
  125 +
  126 +void DvppDec::doProcessReport(){
  127 +
  128 + CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed");
  129 + // 阻塞等待vdec线程开始
  130 +
  131 + int ret;
  132 + while (!m_bExitReportThd) {
  133 + aclrtProcessReport(1000);
  134 + }
  135 +}
  136 +
  137 +static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData)
  138 +{
  139 + Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData;
  140 + if(nullptr != userData){
  141 + DvppDec* self = userData->self;
  142 + if(self != nullptr){
  143 +
  144 + self->doVdppVdecCallBack(input, output);
  145 + }
  146 + delete userData;
  147 + userData = nullptr;
  148 + }
  149 +}
  150 +
  151 +void DvppDec::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output){
  152 +
  153 + CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed");
  154 +
  155 + void *inputDataDev = acldvppGetStreamDescData(input);
  156 + void *outputDataDev = acldvppGetPicDescData(output);
  157 + uint32_t outputSize = acldvppGetPicDescSize(output);
  158 + uint32_t width = acldvppGetPicDescWidth(output);
  159 + uint32_t height = acldvppGetPicDescHeight(output);
  160 +
  161 +
  162 + DvppRgbMemory* rgbMem = picConverter.convert2bgr(output, width, height, false);
  163 + if(rgbMem != nullptr){
  164 +#ifdef TEST_DECODER
  165 + // D2H
  166 + if(vdecHostAddr == nullptr){
  167 + CHECK_NOT_RETURN(aclrtMallocHost(&vdecHostAddr, width * height * 3), "aclrtMallocHost failed");
  168 + }
  169 + uint32_t data_size = rgbMem->getSize();
  170 + CHECK_AND_RETURN_NOVALUE(aclrtMemcpy(vdecHostAddr, data_size, rgbMem->getMem(), data_size, ACL_MEMCPY_DEVICE_TO_HOST), "D2H aclrtMemcpy failed");
  171 +
  172 + // 保存vdec结果
  173 + if(count_frame > 45 && count_frame < 50)
  174 + {
  175 + string file_name = "./yuv_pic/vdec_out_"+ m_dec_name +".rgb" ;
  176 + FILE *outputFile = fopen(file_name.c_str(), "a");
  177 + if(outputFile){
  178 + fwrite(vdecHostAddr, data_size, sizeof(char), outputFile);
  179 + fclose(outputFile);
  180 + }
  181 + }
  182 + else if(count_frame > 50 && vdecHostAddr != nullptr){
  183 + CHECK_NOT_RETURN(aclrtFreeHost(vdecHostAddr), "aclrtFreeHost failed");
  184 + vdecHostAddr = nullptr;
  185 + }
  186 + count_frame++;
  187 +#endif
  188 + post_decoded_cbk(m_postDecArg, rgbMem);
  189 + }else{
  190 + LOG_ERROR("[{}]- convert2bgr failed !", m_dec_name);
  191 + }
  192 +
  193 + acldvppFree((uint8_t*)outputDataDev);
  194 + outputDataDev = nullptr;
  195 +
  196 + m_vdecQueue.addHead();
  197 +
  198 + CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed");
  199 + CHECK_AND_RETURN_NOVALUE(acldvppDestroyPicDesc(output), "acldvppDestroyPicDesc failed");
  200 +}
  201 +
  202 +void DvppDec::close(){
  203 + m_bRunning=false;
  204 +
  205 + if(m_decode_thread != 0){
  206 + pthread_join(m_decode_thread,0);
  207 + }
  208 +}
  209 +
  210 +bool DvppDec::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc){
  211 + // create stream desc
  212 + acldvppStreamDesc *streamInputDesc = acldvppCreateStreamDesc();
  213 + if (streamInputDesc == nullptr) {
  214 + LOG_ERROR("[{}]- fail to create input stream desc", m_dec_name);
  215 + return false;
  216 + }
  217 + aclError ret = acldvppSetStreamDescEos(streamInputDesc, 1);
  218 + if (ret != ACL_SUCCESS) {
  219 + LOG_ERROR("[{}]- fail to set eos for stream desc, errorCode = {}", m_dec_name, static_cast<int32_t>(ret));
  220 + (void)acldvppDestroyStreamDesc(streamInputDesc);
  221 + return false;
  222 + }
  223 +
  224 + // send vdec eos frame. when all vdec callback are completed, aclvdecSendFrame can be returned.
  225 + LOG_INFO("[{}]- send eos", m_dec_name);
  226 + ret = aclvdecSendFrame(vdecChannelDesc, streamInputDesc, nullptr, nullptr, nullptr);
  227 + if (ret != ACL_SUCCESS) {
  228 + LOG_ERROR("[{}]- fail to send eos frame, ret={}", m_dec_name, ret);
  229 + (void)acldvppDestroyStreamDesc(streamInputDesc);
  230 + return false;
  231 + }
  232 + (void)acldvppDestroyStreamDesc(streamInputDesc);
  233 +
  234 + return true;
  235 +}
  236 +
  237 +void DvppDec::releaseResource(){
  238 + for(int i = 0; i < m_vec_vdec.size(); i++){
  239 + if(m_vec_vdec[i] != nullptr){
  240 + acldvppFree(m_vec_vdec[i]);
  241 + m_vec_vdec[i] = nullptr;
  242 + }
  243 + }
  244 + m_vec_vdec.clear();
  245 +
  246 + DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance();
  247 + pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel);
  248 +}
  249 +
  250 +void DvppDec::decode_thread(){
  251 +
  252 + long startTime = UtilTools::get_cur_time_ms();
  253 +
  254 + int ret = -1;
  255 +
  256 + // dvpp解码参数
  257 + CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed");
  258 +
  259 + m_bExitReportThd = false;
  260 + pthread_t report_thread;
  261 + ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this);
  262 + if(ret != 0){
  263 + LOG_ERROR("[{}]- pthread_create failed", m_dec_name);
  264 + return;
  265 + }
  266 +
  267 + // 创建aclvdecChannelDesc类型的数据
  268 + aclvdecChannelDesc *vdecChannelDesc = aclvdecCreateChannelDesc();
  269 + if (vdecChannelDesc == nullptr) {
  270 + LOG_ERROR("[{}]- aclvdecCreateChannelDesc failed", m_dec_name);
  271 + return;
  272 + }
  273 + do{
  274 + // 创建 channel dec结构体
  275 + // 通道ID在dvpp层面为0~31
  276 + CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed");
  277 + CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed");
  278 + CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed");
  279 + CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed");
  280 + CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed");
  281 + CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed");
  282 +
  283 + uint64_t frame_count = 0;
  284 + bool bBreak = false;
  285 + while (m_bRunning)
  286 + {
  287 + if (m_bPause){
  288 + std::this_thread::sleep_for(std::chrono::milliseconds(10));
  289 + continue;
  290 + }
  291 + int ret = sentFrame(vdecChannelDesc, frame_count);
  292 + if(ret == 2){
  293 + break;
  294 + bBreak = true;
  295 + }else if(ret == 1){
  296 + continue;
  297 + }
  298 +
  299 + frame_count++;
  300 + }
  301 +
  302 + // 尽量保证数据全部解码完成
  303 + int sum = 0;
  304 + if(!bBreak){
  305 + while(!m_pktQueueptr->isEmpty()){
  306 + int ret = sentFrame(vdecChannelDesc, frame_count);
  307 + if(ret == 2){
  308 + break;
  309 + }
  310 + std::this_thread::sleep_for(std::chrono::milliseconds(3));
  311 + sum++;
  312 + if(sum > 40){
  313 + // 避免卡死
  314 + break;
  315 + }
  316 + }
  317 + }
  318 +
  319 + sendVdecEos(vdecChannelDesc);
  320 +
  321 + CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed");
  322 + }while(0);
  323 +
  324 + CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed");
  325 +
  326 + // report_thread 需后于destroy退出
  327 + m_bRunning = false;
  328 + m_bExitReportThd = true;
  329 + CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed");
  330 +
  331 + releaseResource();
  332 + LOG_INFO("[{}]- decode thread exit.", m_dec_name);
  333 +}
  334 +
  335 +int DvppDec::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count){
  336 +
  337 + AVPacket * pkt = m_pktQueueptr->getHead();
  338 + if(pkt == nullptr){
  339 + std::this_thread::sleep_for(std::chrono::milliseconds(10));
  340 + return 1;
  341 + }
  342 + // 解码
  343 + void *vdecInputbuf = m_vdecQueue.getTail();
  344 + if(vdecInputbuf == nullptr){
  345 + std::this_thread::sleep_for(std::chrono::milliseconds(3));
  346 + return 1;
  347 + }
  348 +
  349 + int ret = aclrtMemcpy(vdecInputbuf, pkt->size, pkt->data, pkt->size, ACL_MEMCPY_HOST_TO_DEVICE);
  350 + if(ACL_ERROR_NONE != ret){
  351 + LOG_ERROR("[{}]- aclrtMemcpy failed", m_dec_name);
  352 + return 2;
  353 + }
  354 +
  355 + void *vdecOutputBuf = nullptr;
  356 + ret = acldvppMalloc((void **)&vdecOutputBuf, m_vdec_out_size);
  357 + if(ret != ACL_ERROR_NONE){
  358 + LOG_ERROR("[{}]- acldvppMalloc failed", m_dec_name);
  359 + return 2;
  360 + }
  361 +
  362 + acldvppStreamDesc *input_stream_desc = nullptr;
  363 + acldvppPicDesc *output_pic_desc = nullptr;
  364 + do{
  365 + input_stream_desc = acldvppCreateStreamDesc();
  366 + if (input_stream_desc == nullptr) {
  367 + LOG_ERROR("[{}]- acldvppCreateStreamDesc failed", m_dec_name);
  368 + break;
  369 + }
  370 + output_pic_desc = acldvppCreatePicDesc();
  371 + if (output_pic_desc == nullptr) {
  372 + LOG_ERROR("[{}]- acldvppCreatePicDesc failed", m_dec_name);
  373 + break;
  374 + }
  375 + CHECK_AND_BREAK(acldvppSetStreamDescData(input_stream_desc, vdecInputbuf), "acldvppSetStreamDescData failed");
  376 + CHECK_AND_BREAK(acldvppSetStreamDescSize(input_stream_desc, pkt->size), "acldvppSetStreamDescSize failed");
  377 + CHECK_AND_BREAK(acldvppSetPicDescData(output_pic_desc, vdecOutputBuf), "acldvppSetPicDescData failed");
  378 + CHECK_AND_BREAK(acldvppSetPicDescSize(output_pic_desc, m_vdec_out_size), "acldvppSetPicDescSize failed");
  379 +
  380 + Vdec_CallBack_UserData *user_data = NULL;
  381 + user_data = new Vdec_CallBack_UserData;
  382 + user_data->frameId = frame_count;
  383 + // user_data->startTime = startTime;
  384 + user_data->sendTime = UtilTools::get_cur_time_ms();
  385 + user_data->self = this;
  386 + ret = aclvdecSendFrame(vdecChannelDesc, input_stream_desc, output_pic_desc, nullptr, reinterpret_cast<void *>(user_data));
  387 + av_packet_unref(pkt);
  388 + m_pktQueueptr->addHead();
  389 + if(ret != ACL_ERROR_NONE){
  390 + delete user_data;
  391 + user_data = nullptr;
  392 + LOG_ERROR("[{}]- aclvdecSendFrame failed", m_dec_name);
  393 + break;
  394 + }
  395 +
  396 + m_vdecQueue.addTail();
  397 +
  398 + return 0;
  399 + }while (0);
  400 +
  401 + // 报错情形
  402 + if(input_stream_desc){
  403 + CHECK_NOT_RETURN(acldvppDestroyStreamDesc(input_stream_desc), "acldvppDestroyStreamDesc failed");
  404 + }
  405 + if(output_pic_desc){
  406 + CHECK_NOT_RETURN(acldvppDestroyPicDesc(output_pic_desc), "acldvppDestroyPicDesc failed");
  407 + }
  408 +
  409 + acldvppFree(vdecOutputBuf);
  410 + vdecOutputBuf = nullptr;
  411 +
  412 + return 1;
  413 +}
  414 +
  415 +
  416 +void DvppDec::setPostDecArg(const void* postDecArg){
  417 + m_postDecArg = postDecArg;
  418 +}
  419 +
  420 +void DvppDec::pause(){
  421 + m_bPause = true;
  422 +}
  423 +
  424 +void DvppDec::resume(){
  425 + m_bPause = false;
  426 +}
0 427 \ No newline at end of file
... ...
src/dvpp/DvppDec.h 0 → 100644
  1 +#include<string>
  2 +#include <pthread.h>
  3 +
  4 +#include "dvpp_headers.h"
  5 +#include "depend_headers.h"
  6 +#include "user_mem.h"
  7 +#include "CircularQueue.hpp"
  8 +#include "VpcPicConverter.h"
  9 +#include "FFReceiver.h"
  10 +
  11 +#include <queue>
  12 +
  13 +using namespace std;
  14 +
  15 +#define TEST_DECODER
  16 +
  17 +struct DvppDecConfig{
  18 + string dec_name;
  19 + POST_DECODE_CALLBACK post_decoded_cbk; // 解码数据回调接口
  20 + string dev_id; // gpu id
  21 + bool force_tcp{true}; // 是否指定使用tcp连接
  22 + int skip_frame{1}; // 跳帧数
  23 + int codec_id; // 0 : h264 1:h265
  24 + int profile;
  25 + CircularQueue<AVPacket*> *pktQueueptr;
  26 +
  27 + int width;
  28 + int height;
  29 +};
  30 +
  31 +
  32 +class DvppDec {
  33 +public:
  34 + DvppDec();
  35 + ~DvppDec();
  36 + bool init_vdpp(DvppDecConfig cfg);
  37 + void setPostDecArg(const void* postDecArg);
  38 + bool start();
  39 + void close();
  40 + void pause();
  41 + void resume();
  42 +
  43 +public:
  44 + void doProcessReport();
  45 + void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output);
  46 +
  47 +private:
  48 + void decode_thread();
  49 + void releaseResource();
  50 + bool sendVdecEos(aclvdecChannelDesc *vdecChannelDesc);
  51 + int sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count);
  52 +
  53 +private:
  54 +
  55 + bool m_bRunning{false};
  56 + bool m_bPause{false};
  57 + bool m_bExitReportThd{false};
  58 +
  59 + int m_dvpp_deviceId {-1};
  60 + int m_dvpp_channel {-1};
  61 + aclrtContext m_context;
  62 + acldvppStreamFormat enType;
  63 +
  64 + pthread_t m_decode_thread;
  65 +
  66 + DvppDecConfig m_cfg;
  67 + string m_dec_name;
  68 +
  69 + vector<void*> m_vec_vdec;
  70 + CircularQueue<void *> m_vdecQueue;
  71 + CircularQueue<AVPacket *> *m_pktQueueptr;
  72 +
  73 + const void * m_postDecArg;
  74 + POST_DECODE_CALLBACK post_decoded_cbk;
  75 +
  76 + VpcPicConverter picConverter;
  77 +
  78 + int m_vdec_out_size {-1};
  79 +
  80 +#ifdef TEST_DECODER
  81 + void *vdecHostAddr = nullptr;
  82 + int count_frame = 0;
  83 +#endif
  84 +
  85 +};
0 86 \ No newline at end of file
... ...
src/dvpp/DvppDecoder.cpp 0 → 100644
  1 +#include "DvppDecoder.h"
  2 +
  3 +void receiver_finish_cbk(const void* userPtr){
  4 + if(userPtr != nullptr){
  5 + DvppDecoder* self = (DvppDecoder*)userPtr;
  6 + self->taskFinishing();
  7 + }
  8 +}
  9 +
  10 +DvppDecoder::DvppDecoder(){
  11 + m_pktQueueptr = new CircularQueue<AVPacket *>();
  12 +}
  13 +
  14 +DvppDecoder::~DvppDecoder(){
  15 + delete m_pktQueueptr;
  16 + m_pktQueueptr = nullptr;
  17 +}
  18 +
  19 +bool DvppDecoder::init(FFDecConfig cfg){
  20 +
  21 + m_dec_name = cfg.dec_name;
  22 +
  23 + ReceiverConfig receiver_config;
  24 + receiver_config.uri = cfg.uri.c_str();
  25 + receiver_config.dec_name = cfg.dec_name;
  26 + receiver_config.force_tcp = cfg.force_tcp;
  27 + receiver_config.pktQueueptr = m_pktQueueptr;
  28 + receiver_config.receiver_finished_cbk = receiver_finish_cbk;
  29 + AVCodecContext* avctx = m_receiver.init_FFmpeg(receiver_config);
  30 + if(avctx == nullptr){
  31 + return false;
  32 + }
  33 + m_receiver.setFinishCbkArg(this);
  34 +
  35 + DvppDecConfig dec_cfg;
  36 + if(avctx->codec_id == AV_CODEC_ID_H264){
  37 + dec_cfg.codec_id = 0;
  38 + }else if(avctx->codec_id == AV_CODEC_ID_HEVC){
  39 + dec_cfg.codec_id = 1;
  40 + }else {
  41 + return false;
  42 + }
  43 + dec_cfg.dec_name = cfg.dec_name;
  44 + dec_cfg.post_decoded_cbk = cfg.post_decoded_cbk;
  45 + dec_cfg.dev_id = cfg.gpuid;
  46 + dec_cfg.force_tcp = cfg.force_tcp;
  47 + dec_cfg.skip_frame = cfg.skip_frame;
  48 + dec_cfg.profile = avctx->profile;
  49 + dec_cfg.pktQueueptr = m_pktQueueptr;
  50 + dec_cfg.width = avctx->width;
  51 + dec_cfg.height = avctx->height;
  52 + bool bRet = m_decoder.init_vdpp(dec_cfg);
  53 + if(!bRet){
  54 + return false;
  55 + }
  56 +
  57 + m_cfg = cfg;
  58 +
  59 + decode_finished_cbk = cfg.decode_finished_cbk;
  60 +
  61 + m_bFinished = false;
  62 +
  63 + return true;
  64 +}
  65 +
  66 +bool DvppDecoder::isSurport(FFDecConfig& cfg){
  67 + return true;
  68 +}
  69 +
  70 +bool DvppDecoder::start(){
  71 + m_receiver.start();
  72 + m_decoder.start();
  73 + return true;
  74 +}
  75 +
  76 +void DvppDecoder::close(){
  77 + m_receiver.close();
  78 +}
  79 +
  80 +void DvppDecoder::setPostDecArg(const void* postDecArg){
  81 + m_decoder.setPostDecArg(postDecArg);
  82 +}
  83 +
  84 +void DvppDecoder::setFinishedDecArg(const void* finishedDecArg){
  85 + m_finishedDecArg = finishedDecArg;
  86 +}
  87 +
  88 +void DvppDecoder::pause(){
  89 + m_receiver.pause();
  90 +}
  91 +
  92 +void DvppDecoder::resume(){
  93 + m_receiver.resume();
  94 +}
  95 +
  96 +void DvppDecoder::setDecKeyframe(bool bKeyframe){
  97 + m_receiver.setDecKeyframe(bKeyframe);
  98 +}
  99 +
  100 +bool DvppDecoder::isRunning(){
  101 + return m_receiver.isRunning();
  102 +}
  103 +
  104 +bool DvppDecoder::isFinished(){
  105 + return m_bFinished;
  106 +}
  107 +
  108 +bool DvppDecoder::isPausing(){
  109 + return m_receiver.isPausing();
  110 +}
  111 +
  112 +bool DvppDecoder::getResolution(int &width, int &height){
  113 + return m_receiver.getResolution(width, height);
  114 +}
  115 +
  116 +float DvppDecoder::fps(){
  117 + return m_receiver.fps();
  118 +}
  119 +
  120 +FFImgInfo* DvppDecoder::snapshot(){
  121 + // TODO
  122 + return nullptr;
  123 +}
  124 +
  125 +int DvppDecoder::getCachedQueueLength(){
  126 + return 0;
  127 +}
  128 +
  129 +void DvppDecoder::taskFinishing(){
  130 + // receiver 中读取线程结束时执行
  131 + m_decoder.close();
  132 + decode_finished_cbk(m_finishedDecArg);
  133 +
  134 + m_bFinished = true;
  135 +
  136 + LOG_INFO("[{}]- task finished.", m_dec_name);
  137 +}
0 138 \ No newline at end of file
... ...
src/dvpp/DvppDecoder.h 0 → 100644
  1 +#include<string>
  2 +
  3 +#include "depend_headers.h"
  4 +#include "CircularQueue.hpp"
  5 +#include "FFReceiver.h"
  6 +#include "DvppDec.h"
  7 +
  8 +using namespace std;
  9 +
  10 +class DvppDecoder{
  11 +public:
  12 + DvppDecoder();
  13 + ~DvppDecoder();
  14 + bool init(FFDecConfig cfg);
  15 + void close();
  16 + bool start();
  17 + void pause();
  18 + void resume();
  19 +
  20 + void setDecKeyframe(bool bKeyframe);
  21 +
  22 + bool isRunning();
  23 + bool isFinished();
  24 + bool isPausing();
  25 + bool getResolution( int &width, int &height );
  26 +
  27 + bool isSurport(FFDecConfig& cfg);
  28 +
  29 + float fps();
  30 +
  31 + void setName(string nm){
  32 + m_dec_name = nm;
  33 + }
  34 +
  35 + string getName(){
  36 + return m_dec_name;
  37 + }
  38 +
  39 + FFImgInfo* snapshot();
  40 +
  41 + void setPostDecArg(const void* postDecArg);
  42 + void setFinishedDecArg(const void* finishedDecArg);
  43 +
  44 + int getCachedQueueLength();
  45 +
  46 +public:
  47 + void taskFinishing();
  48 +
  49 +private:
  50 + FFDecConfig m_cfg;
  51 + string m_dec_name;
  52 +
  53 + CircularQueue<AVPacket *> *m_pktQueueptr;
  54 + FFReceiver m_receiver;
  55 + DvppDec m_decoder;
  56 +
  57 + const void * m_finishedDecArg;
  58 + DECODE_FINISHED_CALLBACK decode_finished_cbk;
  59 +
  60 + bool m_bFinished{false};
  61 +
  62 +};
0 63 \ No newline at end of file
... ...
src/dvpp/DvppDecoderApi.cpp 0 → 100644
  1 +#include "DvppDecoderApi.h"
  2 +#include "DvppDecoder.h"
  3 +
  4 +DvppDecoderApi::DvppDecoderApi(){
  5 + m_pDecoder = nullptr;
  6 +}
  7 +
  8 +DvppDecoderApi::~DvppDecoderApi(){
  9 + if(m_pDecoder != nullptr){
  10 + delete m_pDecoder;
  11 + m_pDecoder = nullptr;
  12 + }
  13 +}
  14 +
  15 +bool DvppDecoderApi::init(FFDecConfig& cfg){
  16 + m_pDecoder = new DvppDecoder();
  17 + if(m_pDecoder != nullptr){
  18 + return m_pDecoder->init(cfg);
  19 + }
  20 + return false;
  21 +}
  22 +
  23 +void DvppDecoderApi::close(){
  24 + if(m_pDecoder != nullptr){
  25 + return m_pDecoder->close();
  26 + }
  27 +}
  28 +
  29 +bool DvppDecoderApi::start(){
  30 + if(m_pDecoder != nullptr){
  31 + return m_pDecoder->start();
  32 + }
  33 + return false;
  34 +}
  35 +
  36 +void DvppDecoderApi::pause(){
  37 + if(m_pDecoder != nullptr){
  38 + return m_pDecoder->pause();
  39 + }
  40 +}
  41 +
  42 +void DvppDecoderApi::resume(){
  43 + if(m_pDecoder != nullptr){
  44 + return m_pDecoder->resume();
  45 + }
  46 +}
  47 +
  48 +void DvppDecoderApi::setDecKeyframe(bool bKeyframe){
  49 + if(m_pDecoder != nullptr){
  50 + return m_pDecoder->setDecKeyframe(bKeyframe);
  51 + }
  52 +}
  53 +
  54 +bool DvppDecoderApi::isRunning(){
  55 + if(m_pDecoder != nullptr){
  56 + return m_pDecoder->isRunning();
  57 + }
  58 + return false;
  59 +}
  60 +
  61 +bool DvppDecoderApi::isFinished(){
  62 + if(m_pDecoder != nullptr){
  63 + return m_pDecoder->isFinished();
  64 + }
  65 + return false;
  66 +}
  67 +
  68 +bool DvppDecoderApi::isPausing(){
  69 + if(m_pDecoder != nullptr){
  70 + return m_pDecoder->isPausing();
  71 + }
  72 + return false;
  73 +}
  74 +
  75 +bool DvppDecoderApi::getResolution(int &width, int &height){
  76 + if(m_pDecoder != nullptr){
  77 + return m_pDecoder->getResolution(width, height);
  78 + }
  79 + return false;
  80 +}
  81 +
  82 +bool DvppDecoderApi::isSurport(FFDecConfig& cfg){
  83 + if(m_pDecoder != nullptr){
  84 + return m_pDecoder->isSurport(cfg);
  85 + }
  86 + return false;
  87 +}
  88 +
  89 +float DvppDecoderApi::fps(){
  90 + if(m_pDecoder != nullptr){
  91 + return m_pDecoder->fps();
  92 + }
  93 + return 0.0;
  94 +}
  95 +
  96 +int DvppDecoderApi::getCachedQueueLength(){
  97 + if(m_pDecoder != nullptr){
  98 + return m_pDecoder->getCachedQueueLength();
  99 + }
  100 + return 0;
  101 +}
  102 +
  103 +void DvppDecoderApi::setName(string nm){
  104 + if(m_pDecoder != nullptr){
  105 + return m_pDecoder->setName(nm);
  106 + }
  107 +}
  108 +
  109 +string DvppDecoderApi::getName(){
  110 + if(m_pDecoder != nullptr){
  111 + return m_pDecoder->getName();
  112 + }
  113 + return nullptr;
  114 +}
  115 +
  116 +FFImgInfo* DvppDecoderApi::snapshot(){
  117 + if(m_pDecoder != nullptr){
  118 + return m_pDecoder->snapshot();
  119 + }
  120 + return nullptr;
  121 +}
  122 +
  123 +void DvppDecoderApi::setPostDecArg(const void* postDecArg){
  124 + if(m_pDecoder != nullptr){
  125 + return m_pDecoder->setPostDecArg(postDecArg);
  126 + }
  127 +}
  128 +
  129 +void DvppDecoderApi::setFinishedDecArg(const void* finishedDecArg){
  130 + if(m_pDecoder != nullptr){
  131 + return m_pDecoder->setFinishedDecArg(finishedDecArg);
  132 + }
  133 +}
0 134 \ No newline at end of file
... ...
src/dvpp/DvppDecoderApi.h 0 → 100644
  1 +#include<string>
  2 +#include <pthread.h>
  3 +
  4 +#include "depend_headers.h"
  5 +#include "../interface/AbstractDecoder.h"
  6 +
  7 +using namespace std;
  8 +
  9 +class DvppDecoder;
  10 +
  11 +class DvppDecoderApi : public AbstractDecoder {
  12 +public:
  13 + DvppDecoderApi();
  14 + ~DvppDecoderApi();
  15 + bool init(FFDecConfig& cfg);
  16 + void close();
  17 + bool start();
  18 + void pause();
  19 + void resume();
  20 +
  21 + void setDecKeyframe(bool bKeyframe);
  22 +
  23 + bool isRunning();
  24 + bool isFinished();
  25 + bool isPausing();
  26 + bool getResolution( int &width, int &height );
  27 +
  28 + bool isSurport(FFDecConfig& cfg);
  29 +
  30 + int getCachedQueueLength();
  31 +
  32 + float fps();
  33 +
  34 + FFImgInfo* snapshot();
  35 +
  36 + DECODER_TYPE getDecoderType(){ return DECODER_TYPE_DVPP; }
  37 + void setName(string nm);
  38 + string getName();
  39 +
  40 + void setPostDecArg(const void* postDecArg);
  41 + void setFinishedDecArg(const void* finishedDecArg);
  42 +private:
  43 + DvppDecoder* m_pDecoder;
  44 +};
0 45 \ No newline at end of file
... ...
src/dvpp/DvppRgbMemory.hpp 0 → 100644
  1 +#include<string>
  2 +
  3 +#include "dvpp_headers.h"
  4 +
  5 +using namespace std;
  6 +
  7 +class DvppRgbMemory : public DeviceRgbMemory
  8 +{
  9 +public:
  10 + DvppRgbMemory(int _channel, int _width, int _height, int _size, string _id, string _dev_id, bool _key_frame)
  11 + :DeviceRgbMemory(_channel, _width, _height, _id, _dev_id, _key_frame, false){
  12 + data_size = _size;
  13 + int ret = acldvppMalloc((void **)&pHwRgb, data_size);
  14 + if(ret != ACL_ERROR_NONE){
  15 + cout << "acldvppMalloc failed" << endl;
  16 + }
  17 + }
  18 +
  19 + ~DvppRgbMemory(){
  20 + if (pHwRgb) {
  21 + acldvppFree((uint8_t*)pHwRgb);
  22 + pHwRgb = nullptr;
  23 + }
  24 + }
  25 +};
0 26 \ No newline at end of file
... ...
src/dvpp/DvppSourceManager.cpp 0 → 100644
  1 +#include "DvppSourceManager.h"
  2 +
  3 +#include "dvpp_headers.h"
  4 +#include "depend_headers.h"
  5 +
  6 +using namespace std;
  7 +
  8 +DvppSourceManager::~DvppSourceManager()
  9 +{
  10 + for(auto iter = ctxMap.begin(); iter != ctxMap.end(); iter++){
  11 + aclError ret = aclrtDestroyContext(iter->second);
  12 + if(ret != ACL_ERROR_NONE){
  13 + LOG_ERROR("aclrtDestroyContext failed !");
  14 + continue;
  15 + }
  16 + }
  17 + ctxMap.clear();
  18 + channelMap.clear();
  19 +
  20 + aclFinalize();
  21 +}
  22 +
  23 +aclrtContext DvppSourceManager::getContext(int devId)
  24 +{
  25 + aclrtContext ctx = ctxMap[devId];
  26 + if (ctx == nullptr)
  27 + {
  28 + // 初始化硬件解码器
  29 + aclError ret = aclrtSetDevice(devId);
  30 + if(ret != ACL_ERROR_NONE){
  31 + // cout << "aclrtSetDevice failed" << endl;
  32 + LOG_ERROR("aclrtSetDevice failed !");
  33 + return nullptr;
  34 + }
  35 +
  36 + ret = aclrtCreateContext(&ctx, devId);
  37 + if (ret != ACL_ERROR_NONE) {
  38 + // cout << "aclrtCreateContext failed " << endl;
  39 + LOG_ERROR("aclrtCreateContext failed !");
  40 + return nullptr;
  41 + }
  42 + ctxMap[devId] = ctx;
  43 + }
  44 + return ctx;
  45 +}
  46 +
  47 +int DvppSourceManager::getChannel(int devId){
  48 + // channel 最大值暂定为32, 华为没有接口获取最大channel,只有文档说明
  49 + for(int iChannel = 0; iChannel < 32; iChannel++){
  50 + string channelKey = "channel_" + to_string(devId) + "_" + to_string(iChannel) ;
  51 + auto it = channelMap.find(channelKey);
  52 + if(it == channelMap.end()){
  53 + channelMap[channelKey] = iChannel;
  54 + return iChannel;
  55 + }
  56 + }
  57 + return -1;
  58 +}
  59 +
  60 +void DvppSourceManager::releaseChannel(int devId, int iChannel){
  61 + string channelKey = "channel_" + to_string(devId) + "_" + to_string(iChannel) ;
  62 + auto it = channelMap.find(channelKey);
  63 + if(it != channelMap.end()){
  64 + channelMap.erase(channelKey);
  65 + }
  66 +}
0 67 \ No newline at end of file
... ...
src/dvpp/DvppSourceManager.h 0 → 100644
  1 +
  2 +#include<map>
  3 +#include<string>
  4 +
  5 +#include "dvpp_headers.h"
  6 +
  7 +using namespace std;
  8 +
  9 +class DvppSourceManager{
  10 +public:
  11 + static DvppSourceManager* getInstance(){
  12 + static DvppSourceManager* singleton = nullptr;
  13 + if (singleton == nullptr){
  14 + singleton = new DvppSourceManager();
  15 + int ret = aclInit(nullptr);
  16 + if (ret != ACL_ERROR_NONE) {
  17 + cout << "aclInit failed" << endl;
  18 + return nullptr;
  19 + }
  20 + }
  21 + return singleton;
  22 + }
  23 +
  24 + aclrtContext getContext(int devId);
  25 +
  26 + int getChannel(int devId);
  27 + void releaseChannel(int devId, int channel);
  28 +
  29 +private:
  30 + DvppSourceManager(){}
  31 + ~DvppSourceManager();
  32 +
  33 +private:
  34 + map<int, aclrtContext> ctxMap;
  35 + map<string, int> channelMap;
  36 +};
0 37 \ No newline at end of file
... ...
src/dvpp/FFReceiver.cpp 0 → 100644
  1 +#include "FFReceiver.h"
  2 +#include <fstream>
  3 +
  4 +const int g_pkt_size = 1024 * 1024; // 单个AVPacket大小的最大值
  5 +
  6 +FFReceiver::FFReceiver(/* args */)
  7 +{
  8 + fmt_ctx = nullptr;
  9 + m_bRunning = false;
  10 +
  11 + stream = nullptr;
  12 + stream_index = -1;
  13 + pix_fmt = AV_PIX_FMT_NONE;
  14 + m_dec_name = "";
  15 +
  16 + m_bPause = false;
  17 + m_bReal = true;
  18 +
  19 + m_bFinished = false;
  20 + m_dec_keyframe = false;
  21 + m_fps = 0.0;
  22 +
  23 + m_read_thread = 0;
  24 +}
  25 +
  26 +FFReceiver::~FFReceiver()
  27 +{
  28 + releaseFFmpeg();
  29 +
  30 + // 这个只能放在析构函数中,因为会影响到解码类中的m_pktQueueptr队列
  31 + // 所以应当确保在所有工作线程都退出后才释放
  32 + for(int i = 0; i < m_vec_pkt.size(); i++){
  33 + av_packet_free(&m_vec_pkt[i]);
  34 + }
  35 +}
  36 +
  37 +AVCodecContext* FFReceiver::init_FFmpeg(ReceiverConfig config){
  38 +
  39 +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
  40 + av_register_all();
  41 +#endif
  42 +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
  43 + avcodec_register_all();
  44 +#endif
  45 +
  46 + avformat_network_init();
  47 +
  48 + const char* uri = config.uri;
  49 + fstream infile(uri);
  50 + if (infile.is_open()){
  51 + m_bReal = false;
  52 + infile.close();
  53 + }else {
  54 + m_bReal = true;
  55 + }
  56 +
  57 + m_dec_name = config.dec_name;
  58 + m_pktQueueptr = config.pktQueueptr;
  59 + receiver_finished_cbk = config.receiver_finished_cbk;
  60 +
  61 + // 打开输入视频文件
  62 + AVDictionary *options = nullptr;
  63 + av_dict_set( &options, "bufsize", "655360", 0 );
  64 + av_dict_set( &options, "rtsp_transport", config.force_tcp ? "tcp" : "udp", 0 );
  65 + av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
  66 +
  67 + fmt_ctx = avformat_alloc_context();
  68 + const char* input_file = uri;
  69 + if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
  70 + LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file);
  71 + return nullptr;
  72 + }
  73 + av_dump_format(fmt_ctx, 0, input_file, 0);
  74 +
  75 + // 查找流信息
  76 + if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
  77 + LOG_ERROR("[{}]- Cannot find input stream information!", m_dec_name);
  78 + return nullptr;
  79 + }
  80 +
  81 + // 查找视频流信息
  82 + AVCodec *decoder = nullptr;
  83 + stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
  84 + if (stream_index < 0) {
  85 + LOG_ERROR("[{}]- Cannot find a video stream in the input file!", m_dec_name);
  86 + return nullptr;
  87 + }
  88 + AVCodec *vcodec = avcodec_find_decoder(decoder->id);
  89 +
  90 + avctx = avcodec_alloc_context3(vcodec);
  91 + if(avctx == nullptr){
  92 + LOG_ERROR("[{}]- alloc AVCodecContext failed!", m_dec_name);
  93 + return nullptr;
  94 + }
  95 +
  96 + do{
  97 + // 得到视频流对象
  98 + AVStream* stream = fmt_ctx->streams[stream_index];
  99 + AVCodecParameters *codecpar = stream->codecpar;
  100 + if (avcodec_parameters_to_context(avctx, codecpar) < 0)
  101 + break;
  102 +
  103 + const AVBitStreamFilter * filter = nullptr;
  104 + if(codecpar->codec_id == AV_CODEC_ID_H264){
  105 + filter = av_bsf_get_by_name("h264_mp4toannexb");
  106 + }else if(codecpar->codec_id == AV_CODEC_ID_HEVC){
  107 + filter = av_bsf_get_by_name("hevc_mp4toannexb");
  108 + }else {
  109 + LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name);
  110 + break;
  111 + }
  112 +
  113 + int ret = av_bsf_alloc(filter, &h264bsfc);
  114 + if (ret < 0){
  115 + break;
  116 + }
  117 +
  118 + avcodec_parameters_copy(h264bsfc->par_in, codecpar);
  119 + av_bsf_init(h264bsfc);
  120 +
  121 + frame_width = codecpar->width;
  122 + frame_height = codecpar->height;
  123 + pix_fmt = (AVPixelFormat)codecpar->format;
  124 + m_fps = av_q2d(stream ->avg_frame_rate);
  125 +
  126 + LOG_INFO("[{}]- init ffmpeg success! input:{} frame_width:{} frame_height:{} fps:{} ", m_dec_name, input_file, frame_width, frame_height, m_fps);
  127 +
  128 + for(int i = 0; i<5; i++){
  129 + AVPacket* pkt = av_packet_alloc();
  130 + av_init_packet( pkt );
  131 + m_vec_pkt.push_back(pkt);
  132 + }
  133 + m_pktQueueptr->init(m_vec_pkt);
  134 +
  135 + return avctx;
  136 + }while(0);
  137 +
  138 + LOG_ERROR("[{}]- init ffmpeg failed ! input:{} ", m_dec_name);
  139 +
  140 + return nullptr;
  141 +}
  142 +
  143 +void FFReceiver::releaseFFmpeg(){
  144 + m_dec_keyframe = false;
  145 + if(h264bsfc){
  146 + av_bsf_free(&h264bsfc);
  147 + h264bsfc = nullptr;
  148 + }
  149 + if (fmt_ctx){
  150 + avformat_close_input(&fmt_ctx);
  151 + fmt_ctx = nullptr;
  152 + }
  153 + if(avctx){
  154 + avcodec_free_context(&avctx);
  155 + avctx = nullptr;
  156 + }
  157 +}
  158 +
  159 +void FFReceiver::read_thread(){
  160 +
  161 + int frame_count = 0;
  162 + int ret = -1;
  163 + while (m_bRunning)
  164 + {
  165 + if (!m_bReal)
  166 + {
  167 + if (m_bPause)
  168 + {
  169 + std::this_thread::sleep_for(std::chrono::milliseconds(3));
  170 + continue;
  171 + }
  172 + }
  173 +
  174 + AVPacket* pkt = m_pktQueueptr->getTail();
  175 + if(pkt == nullptr){
  176 + std::this_thread::sleep_for(std::chrono::milliseconds(3));
  177 + continue;
  178 + }
  179 +
  180 + int result = av_read_frame(fmt_ctx, pkt);
  181 + if (result == AVERROR_EOF || result < 0)
  182 + {
  183 + LOG_ERROR("[{}]- Failed to read frame!", m_dec_name);
  184 + break;
  185 + }
  186 +
  187 + if (m_dec_keyframe && !(pkt->flags & AV_PKT_FLAG_KEY)) {
  188 + av_packet_unref(pkt);
  189 + continue;
  190 + }
  191 +
  192 + if (stream_index == pkt->stream_index){
  193 +
  194 + ret = av_bsf_send_packet(h264bsfc, pkt);
  195 + if(ret < 0) {
  196 + LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name);
  197 + }
  198 +
  199 + while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) {
  200 + if(pkt->size > g_pkt_size){
  201 + LOG_ERROR("[{}]- pkt size 大于最大预设值!", m_dec_name);
  202 + break;
  203 + }
  204 +
  205 + if(!m_bRunning){
  206 + break;
  207 + }
  208 +
  209 + m_pktQueueptr->addTail();
  210 +
  211 + frame_count++;
  212 + }
  213 + }
  214 + }
  215 +
  216 + LOG_INFO("[{}]- read thread exit.", m_dec_name);
  217 + m_bFinished = true;
  218 +
  219 + receiver_finished_cbk(m_finishedReceiveArg);
  220 +}
  221 +
  222 +bool FFReceiver::start(){
  223 + m_bRunning = true;
  224 +
  225 + pthread_create(&m_read_thread,0,
  226 + [](void* arg)
  227 + {
  228 + FFReceiver* a=(FFReceiver*)arg;
  229 + a->read_thread();
  230 + return (void*)0;
  231 + }
  232 + ,this);
  233 +
  234 + return true;
  235 +}
  236 +
  237 +void FFReceiver::close(){
  238 + m_bRunning=false;
  239 +
  240 + if(m_read_thread != 0){
  241 + pthread_join(m_read_thread,0);
  242 + }
  243 +}
  244 +
  245 +float FFReceiver::fps(){
  246 + return m_fps;
  247 +}
  248 +
  249 +bool FFReceiver::getResolution( int &width, int &height ){
  250 + width = frame_width;
  251 + height = frame_height;
  252 + return true;
  253 +}
  254 +
  255 +void FFReceiver::pause(){
  256 + m_bPause = true;
  257 +}
  258 +
  259 +void FFReceiver::resume(){
  260 + m_bPause = false;
  261 +}
  262 +
  263 +void FFReceiver::setDecKeyframe(bool bKeyframe)
  264 +{
  265 + m_dec_keyframe = bKeyframe;
  266 +}
  267 +
  268 +bool FFReceiver::isRunning(){
  269 + return m_bRunning;
  270 +}
  271 +
  272 +bool FFReceiver::isFinished(){
  273 + return m_bFinished;
  274 +}
  275 +
  276 +bool FFReceiver::isPausing(){
  277 + return m_bPause;
  278 +}
  279 +
  280 +void FFReceiver::setFinishCbkArg(const void* userPtr){
  281 + m_finishedReceiveArg = userPtr;
  282 +}
0 283 \ No newline at end of file
... ...
src/dvpp/FFReceiver.h 0 → 100644
  1 +#ifndef __FFRECEIVER_H__
  2 +#define __FFRECEIVER_H__
  3 +
  4 +#include "depend_headers.h"
  5 +#include "CircularQueue.hpp"
  6 +
  7 +typedef void(*RECEIVER_FINISHED_CALLBACK)(const void* userPtr);
  8 +
  9 +struct ReceiverConfig{
  10 + const char* uri;
  11 + string dec_name;
  12 + bool force_tcp;
  13 + CircularQueue<AVPacket*> *pktQueueptr;
  14 + RECEIVER_FINISHED_CALLBACK receiver_finished_cbk; // 解码线程结束后的回调接口
  15 +};
  16 +
  17 +class FFReceiver
  18 +{
  19 +public:
  20 + FFReceiver(/* args */);
  21 + ~FFReceiver();
  22 +
  23 + AVCodecContext* init_FFmpeg(ReceiverConfig config);
  24 + void releaseFFmpeg();
  25 + void close();
  26 + bool start();
  27 +
  28 + void pause();
  29 + void resume();
  30 + void setDecKeyframe(bool bKeyframe);
  31 + bool isRunning();
  32 + bool isFinished();
  33 + bool isPausing();
  34 + bool getResolution( int &width, int &height );
  35 + float fps();
  36 +
  37 + void setName(string nm){
  38 + m_dec_name = nm;
  39 + }
  40 +
  41 + void setFinishCbkArg(const void* userPtr);
  42 +
  43 +private:
  44 + void read_thread();
  45 +
  46 +private:
  47 + string m_dec_name;
  48 +
  49 + AVStream* stream;
  50 + int stream_index;
  51 + AVFormatContext *fmt_ctx;
  52 + AVPixelFormat pix_fmt;
  53 + int frame_width{0};
  54 + int frame_height{0};
  55 +
  56 + pthread_t m_read_thread;
  57 +
  58 + bool m_bRunning;
  59 + bool m_bFinished;
  60 +
  61 + bool m_bPause;
  62 +
  63 + bool m_bReal; // 是否实时流
  64 +
  65 + float m_fps;
  66 +
  67 + FFDecConfig m_cfg;
  68 + bool m_dec_keyframe;
  69 +
  70 + AVCodecContext *avctx{nullptr};
  71 + AVBSFContext * h264bsfc{nullptr};
  72 +
  73 + vector<AVPacket*> m_vec_pkt;
  74 + CircularQueue<AVPacket *> *m_pktQueueptr;
  75 +
  76 + const void * m_finishedReceiveArg;
  77 + RECEIVER_FINISHED_CALLBACK receiver_finished_cbk;
  78 +};
  79 +
  80 +
  81 +#endif
0 82 \ No newline at end of file
... ...
src/dvpp/Makefile 0 → 100644
  1 +# 各项目录
  2 +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib
  3 +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep
  4 +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj
  5 +SRC_DIR:=$(TOP_DIR)/$(MODULE)
  6 +
  7 +# 源文件以及中间目标文件和依赖文件
  8 +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp))
  9 +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS)))
  10 +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS)))
  11 +
  12 +# 自动生成头文件依赖选项
  13 +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
  14 +
  15 +DEFS = -DENABLE_DVPP_INTERFACE
  16 +
  17 +# 最终目标文件
  18 +TARGET:=$(LIB_DIR)/$(MODULE).a
  19 +
  20 +export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/runtime/lib64:$LD_LIBRARY_PATH
  21 +export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/6.3.RC1.alpha001/lib64:$LD_LIBRARY_PATH
  22 +export LD_LIBRARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBRARY_PATH
  23 +
  24 +include_dir=-I/usr/local/Ascend/ascend-toolkit/latest/acllib/include
  25 +lib_dir=-L/usr/lib -L/usr/local/lib -L/usr/local/Ascend/ascend-toolkit/latest/acllib/lib64 -L/usr/local/Ascend/driver/lib64 -L/usr/local/Ascend/ascend-toolkit/latest/atc/lib64
  26 +lib=-lacl_dvpp -lascendcl -lmmpa -lglog -lgflags -lpthread -lz
  27 +
  28 +CXXFLAGS= -g -O0 -fPIC $(include_dir) $(INCS) $(LIBS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl
  29 + # -DUNICODE -D_UNICODE
  30 +
  31 +# 默认最终目标
  32 +.PHONY:all
  33 +all:$(TARGET)
  34 +
  35 +# 生成最终目标
  36 +$(TARGET):$(OBJS) | $(LIB_DIR)
  37 + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m"
  38 + @ar -rc $@ $^
  39 +
  40 +# 若没有lib目录则自动生成
  41 +$(LIB_DIR):
  42 + @mkdir -p $@
  43 +
  44 +# 生成中间目标文件
  45 +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR)
  46 + @echo -e "\e[33m""Building object $@""\e[0m"
  47 + @$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(lib_dir) $(lib) $(MACROS) -o $@ $<
  48 +
  49 +# 若没有obj目录则自动生成
  50 +$(OBJ_DIR):
  51 + @mkdir -p $@
  52 +
  53 +# 若没有.dep目录则自动生成
  54 +$(DEP_DIR):
  55 + @mkdir -p $@
  56 +
  57 +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错
  58 +$(DEPS):
  59 +
  60 +# 引入中间目标文件头文件依赖关系
  61 +include $(wildcard $(DEPS))
  62 +
  63 +# 直接删除组件build目录
  64 +.PHONY:clean
  65 +clean:
  66 + @rm -rf $(BUILD_DIR)/$(MODULE)
... ...
src/dvpp/VpcPicConverter.cpp 0 → 100644
  1 +#include "VpcPicConverter.h"
  2 +#include "depend_headers.h"
  3 +
  4 +#define ALIGN_UP(val, align) (((val) % (align) == 0) ? (val) : (((val) / (align) + 1) * (align)))
  5 +
  6 +VpcPicConverter::VpcPicConverter(){
  7 +
  8 +}
  9 +
  10 +VpcPicConverter::~VpcPicConverter(){
  11 + if(nullptr == stream_){
  12 + aclrtDestroyStream(stream_);
  13 + }
  14 +}
  15 +
  16 +int VpcPicConverter::init(aclrtContext context, string dec_name){
  17 +
  18 + m_dec_name = dec_name;
  19 +
  20 + CHECK_AND_RETURN(aclrtSetCurrentContext(context), "aclrtSetCurrentContext failed");
  21 + CHECK_AND_RETURN(aclrtCreateStream(&stream_), "aclrtCreateStream failed! ");
  22 +
  23 + dvppChannelDesc_ = acldvppCreateChannelDesc();
  24 +
  25 + int ret = ACL_ERROR_NONE;
  26 + do
  27 + {
  28 + ret = acldvppCreateChannel(dvppChannelDesc_);
  29 + CHECK_AND_BREAK(ret, "acldvppCreateChannel failed !");
  30 +
  31 + ret = acldvppSetChannelDescMode(dvppChannelDesc_, DVPP_CHNMODE_VPC);
  32 + CHECK_AND_BREAK(ret, "acldvppSetChannelDescMode failed !");
  33 + } while (0);
  34 +
  35 + return ret;
  36 +}
  37 +
  38 +DvppRgbMemory* VpcPicConverter::convert2bgr(acldvppPicDesc *inputDesc_, int out_width, int out_height, bool key_frame){
  39 +
  40 + int out_buf_width = ALIGN_UP(out_width, 16) * 3;
  41 + int out_buf_height = ALIGN_UP(out_height, 2);
  42 + int out_buf_size = out_buf_width * out_buf_height;
  43 +
  44 + DvppRgbMemory* rgbMem = new DvppRgbMemory(3, out_buf_width, out_buf_height, out_buf_size, "", to_string(m_devId), key_frame);
  45 + void *outBufferDev_ = (void*)rgbMem->getMem();
  46 +
  47 + acldvppPicDesc *outputDesc_= acldvppCreatePicDesc();
  48 + acldvppSetPicDescData(outputDesc_, outBufferDev_);
  49 + acldvppSetPicDescFormat(outputDesc_, PIXEL_FORMAT_BGR_888);
  50 + acldvppSetPicDescWidth(outputDesc_, out_width);
  51 + acldvppSetPicDescHeight(outputDesc_, out_height);
  52 + acldvppSetPicDescWidthStride(outputDesc_, out_buf_width);
  53 + acldvppSetPicDescHeightStride(outputDesc_, out_buf_height);
  54 + acldvppSetPicDescSize(outputDesc_, out_buf_size);
  55 +
  56 + aclError ret = ACL_ERROR_NONE;
  57 + do{
  58 + // 9. 执行异步色域转换,再调用aclrtSynchronizeStream接口阻塞程序运行,直到指定Stream中的所有任务都完成
  59 + ret = acldvppVpcConvertColorAsync(dvppChannelDesc_, inputDesc_, outputDesc_, stream_);
  60 + if(ret != ACL_ERROR_NONE){
  61 + LOG_ERROR("acldvppVpcConvertColorAsync failed - out_width:{} out_height:{} out_buf_width:{} out_buf_height:{} out_buf_size:{}", out_width, out_height, out_buf_width, out_buf_height, out_buf_size);
  62 + break;
  63 + }
  64 + ret = aclrtSynchronizeStream(stream_);
  65 + if(ret != ACL_ERROR_NONE){
  66 + LOG_ERROR("aclrtSynchronizeStream failed - out_width:{} out_height:{} out_buf_width:{} out_buf_height:{} out_buf_size:{}", out_width, out_height, out_buf_width, out_buf_height, out_buf_size);
  67 + break;
  68 + }
  69 + }while(0);
  70 +
  71 + acldvppDestroyPicDesc(outputDesc_);
  72 +
  73 + if(ret != ACL_ERROR_NONE){
  74 + delete rgbMem;
  75 + rgbMem = nullptr;
  76 + }
  77 +
  78 + return rgbMem;
  79 +}
0 80 \ No newline at end of file
... ...
src/dvpp/VpcPicConverter.h 0 → 100644
  1 +#include "dvpp_headers.h"
  2 +#include "depend_headers.h"
  3 +#include "DvppRgbMemory.hpp"
  4 +
  5 +
  6 +class VpcPicConverter{
  7 +public:
  8 + VpcPicConverter();
  9 + ~VpcPicConverter();
  10 + int init(aclrtContext context, string dec_name);
  11 +
  12 + DvppRgbMemory* convert2bgr(acldvppPicDesc *input, int out_width, int out_height, bool key_frame);
  13 +
  14 +private:
  15 + aclrtContext context_;
  16 + aclrtStream stream_;
  17 + int m_devId;
  18 + acldvppChannelDesc *dvppChannelDesc_ ;
  19 + string m_dec_name;
  20 +};
0 21 \ No newline at end of file
... ...
src/dvpp/depend_headers.h 0 → 100644
  1 +#ifndef __DEPEND_HEADERS_H__
  2 +#define __DEPEND_HEADERS_H__
  3 +
  4 +#include <iostream>
  5 +#include <utility>
  6 +#include <chrono>
  7 +#include <thread>
  8 +#include <functional>
  9 +#include <atomic>
  10 +#include <fstream>
  11 +#include <signal.h>
  12 +#include <time.h>
  13 +#include <unistd.h>
  14 +#include <set>
  15 +#include <mutex>
  16 +#include <vector>
  17 +#include <condition_variable>
  18 +
  19 +/*
  20 +* 依赖模块外部的代码或库
  21 +* 不要在此处添加模块内部的头文件
  22 +*/
  23 +
  24 +// ffmpeg 是c库 所以编译的时候要加入从 extern导入的C 来声明否则连接失败
  25 +extern "C" {
  26 + #include "libavutil/imgutils.h"
  27 + #include "libavutil/samplefmt.h"
  28 + #include "libavformat/avformat.h"
  29 + #include "libavcodec/avcodec.h"
  30 +}
  31 +
  32 +
  33 +#include "../interface/logger.hpp"
  34 +#include "../interface/DeviceRgbMemory.hpp"
  35 +#include "../interface/interface_headers.h"
  36 +#include "../interface/utiltools.hpp"
  37 +
  38 +#endif
0 39 \ No newline at end of file
... ...
src/dvpp/dvpp_headers.h 0 → 100644
  1 +/*
  2 +* 模块内部的头文件请在此处添加
  3 +*/
  4 +
  5 +#ifndef __DVPP_HEADERS_H__
  6 +#define __DVPP_HEADERS_H__
  7 +
  8 +#include <iostream>
  9 +#include <utility>
  10 +#include <chrono>
  11 +#include <thread>
  12 +#include <functional>
  13 +#include <atomic>
  14 +#include <fstream>
  15 +#include <signal.h>
  16 +#include <time.h>
  17 +#include <unistd.h>
  18 +#include <set>
  19 +#include <mutex>
  20 +#include <vector>
  21 +#include <condition_variable>
  22 +
  23 +#include "acl/acl_mdl.h"
  24 +#include "acl/acl_base.h"
  25 +#include "acl/acl_rt.h"
  26 +#include "acl/acl.h"
  27 +#include "acl/ops/acl_dvpp.h"
  28 +
  29 +
  30 +#define CHECK_AND_RETURN(ret, message) \
  31 + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return ret;}
  32 +#define CHECK_NOT_RETURN(ret, message) \
  33 + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message);}
  34 +#define CHECK_AND_RETURN_NOVALUE(ret, message) \
  35 + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return;}
  36 +#define CHECK_AND_BREAK(ret, message) \
  37 + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); break;}
  38 +
  39 +#endif
  40 +
... ...
src/dvpp/threadsafe_queue.h 0 → 100644
  1 +
  2 +#ifndef __THREADSAFE_QUEUE_H__
  3 +#define __THREADSAFE_QUEUE_H__
  4 +
  5 +#include <queue>
  6 +#include <mutex>
  7 +#include <condition_variable>
  8 +#include <initializer_list>
  9 +
  10 +#include <pthread.h>
  11 +using std::queue;
  12 +using namespace std;
  13 +
  14 +template <typename T>
  15 +class ThreadedQueue : public queue<T> {
  16 +public:
  17 + ThreadedQueue();
  18 + ~ThreadedQueue();
  19 + bool empty() const;
  20 + size_t size() const;
  21 + void push(const T& val);
  22 + void push(T& val);
  23 + bool pop();
  24 + T& front();
  25 + const T& front() const;
  26 + T& back();
  27 + const T& back() const;
  28 +
  29 + void Put(T &data);
  30 +
  31 + T Take();
  32 + void Get(T &data);
  33 + bool GetEmpty();
  34 +
  35 + condition_variable *condition;
  36 + mutex *lock;
  37 +};
  38 +
  39 +template <typename T>
  40 +ThreadedQueue<T>::ThreadedQueue() {
  41 + lock = new mutex;
  42 + condition = new condition_variable;
  43 +}
  44 +
  45 +template <typename T>
  46 +ThreadedQueue<T>::~ThreadedQueue() {
  47 + if(condition != nullptr){
  48 + delete condition;
  49 + condition = nullptr;
  50 + }
  51 + if(lock != nullptr){
  52 + delete lock;
  53 + lock = nullptr;
  54 + }
  55 +}
  56 +
  57 +template <typename T>
  58 +T ThreadedQueue<T>:: Take()
  59 +{
  60 + std::unique_lock<std::mutex> lk(this->lock);
  61 + this->condition->wait(lk, [this]{return !this->empty();});
  62 + T val = this->front();
  63 + this->pop();
  64 + return val;
  65 +}
  66 +
  67 +template <typename T>
  68 +void ThreadedQueue<T>:: Put(T &data)
  69 +{
  70 + std::unique_lock<std::mutex> lk(*lock);
  71 + this->push(data);
  72 + this->condition->notify_one();
  73 + return;
  74 +}
  75 +
  76 +template <typename T>
  77 +void ThreadedQueue<T>:: Get(T &data)
  78 +{
  79 + std::unique_lock<std::mutex> lk(*lock);
  80 + this->condition->wait(lk, [this]{return !this->empty();});
  81 + data = this->front();
  82 + this->pop();
  83 +}
  84 +
  85 +template <typename T>
  86 +bool ThreadedQueue<T>::GetEmpty()
  87 +{
  88 + std::unique_lock<std::mutex> lk(*lock);
  89 + this->condition->wait(lk, [this]{return !this->empty();});
  90 + return true;
  91 +}
  92 +
  93 +
  94 +template <typename T>
  95 +bool ThreadedQueue<T>::empty() const {
  96 + bool result = queue<T>::empty();
  97 + return result;
  98 +}
  99 +
  100 +template <typename T>
  101 +size_t ThreadedQueue<T>::size() const {
  102 + size_t result = queue<T>::size();
  103 + return result;
  104 +}
  105 +
  106 +template <typename T>
  107 +void ThreadedQueue<T>::push(T& val) {
  108 + queue<T>::push(val);
  109 +}
  110 +
  111 +
  112 +template <typename T>
  113 +T& ThreadedQueue<T>::front() {
  114 + T& result = queue<T>::front();
  115 + return result;
  116 +}
  117 +
  118 +template <typename T>
  119 +bool ThreadedQueue<T>::pop() {
  120 + bool result = false;
  121 + if(!queue<T>::empty()) {
  122 + queue<T>::pop();
  123 + result = true;
  124 + }
  125 + return result;
  126 +}
  127 +
  128 +#endif
... ...
src/dvpp/user_mem.h 0 → 100644
  1 +#ifndef __USER_MEM_H__
  2 +#define __USER_MEM_H__
  3 +
  4 +#include <mutex>
  5 +#include <memory>
  6 +#include <iostream>
  7 +#include <condition_variable>
  8 +#include "threadsafe_queue.h"
  9 +
  10 +#define ALIGN_MEM(val, align) (((val) % (align) == 0) ? (val) : (((val) / (align) + 1) * (align)))
  11 +
  12 +using namespace std;
  13 +
  14 +typedef enum {
  15 + RTSP_MEM,
  16 + VDEC_MEM,
  17 +} MemType;
  18 +
  19 +class MemNode{
  20 +public:
  21 + uint8_t *bufAddr;
  22 + MemType memType;
  23 +
  24 + MemNode(){
  25 + std::cout << "构造" << endl;
  26 + }
  27 +
  28 + ~MemNode(){
  29 + std::cout << "析构" << std::endl;
  30 + }
  31 +} ;
  32 +
  33 +#endif
0 34 \ No newline at end of file
... ...
src/gb28181/FFGB28181Decoder.cpp
... ... @@ -2,7 +2,7 @@
2 2 #include <iostream>
3 3 #include "FFGB28181Decoder.h"
4 4  
5   -#include "../FFCuContextManager.h"
  5 +
6 6  
7 7 extern "C" {
8 8 #include "libavutil/avstring.h"
... ... @@ -17,6 +17,10 @@ extern &quot;C&quot; {
17 17  
18 18 #include "common_header.h"
19 19  
  20 +#include "../nvdec/FFCuContextManager.h"
  21 +#include "../nvdec/GpuRgbMemory.hpp"
  22 +#include "../nvdec/cuda_kernels.h"
  23 +
20 24 #define ECLOSED 0
21 25 #define ECLOSING 1
22 26 #define ERUNNING 2
... ... @@ -300,7 +304,7 @@ void FFGB28181Decoder::post_decode_thread(){
300 304 m_queue_mutex.unlock();
301 305 // 跳帧
302 306 if (m_frameSkip == 1 || index % m_frameSkip == 0){
303   - post_decoded_cbk(m_postDecArg, gpuFrame);
  307 + post_decoded_cbk(m_postDecArg, convert2bgr(gpuFrame));
304 308 }
305 309  
306 310 av_frame_free(&gpuFrame);
... ... @@ -325,6 +329,14 @@ void FFGB28181Decoder::stream_end_callback()
325 329 return;
326 330 }
327 331  
  332 +void FFGB28181Decoder::setPostDecArg(const void* postDecArg){
  333 + m_postDecArg = postDecArg;
  334 +}
  335 +
  336 +void FFGB28181Decoder::setFinishedDecArg(const void* finishedDecArg){
  337 + m_finishedDecArg = finishedDecArg;
  338 +}
  339 +
328 340 void FFGB28181Decoder::pause() {
329 341 m_status = EPAUSE;
330 342 LOG_INFO("pause --{}", m_dec_name);
... ... @@ -373,4 +385,120 @@ bool FFGB28181Decoder::isSurport(FFDecConfig&amp; cfg){
373 385  
374 386 int FFGB28181Decoder::getCachedQueueLength(){
375 387 return m_rtpPtr->GetPsFrameListSize();
  388 +}
  389 +
  390 +DeviceRgbMemory* FFGB28181Decoder::convert2bgr(AVFrame * gpuFrame){
  391 + if (gpuFrame != nullptr && gpuFrame->format == AV_PIX_FMT_CUDA ){
  392 + LOG_DEBUG("decode task: gpuid: {} width: {} height: {}", m_cfg.gpuid, gpuFrame->width, gpuFrame->height);
  393 + GpuRgbMemory* gpuMem = new GpuRgbMemory(3, gpuFrame->width, gpuFrame->height, getName(), m_cfg.gpuid, false, true);
  394 +
  395 + do{
  396 + if (gpuMem->getMem() == nullptr){
  397 + LOG_ERROR("new GpuRgbMemory failed !!!");
  398 + break;
  399 + }
  400 +
  401 + cudaSetDevice(atoi(m_cfg.gpuid.c_str()));
  402 + cuda_common::setColorSpace( ITU_709, 0 );
  403 + cudaError_t cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], gpuMem->getMem(), gpuFrame->width, gpuFrame->height);
  404 + cudaDeviceSynchronize();
  405 + if (cudaStatus != cudaSuccess) {
  406 + LOG_ERROR("CUDAToBGR failed failed !!!");
  407 + break;
  408 + }
  409 +
  410 + return gpuMem;
  411 + }while(0);
  412 +
  413 + delete gpuMem;
  414 + gpuMem = nullptr;
  415 + }
  416 +
  417 + return nullptr;
  418 +}
  419 +
  420 +FFImgInfo* FFGB28181Decoder::snapshot(){
  421 +
  422 + // 锁住停止队列消耗
  423 + std::lock_guard<std::mutex> l(m_snapshot_mutex);
  424 +
  425 + AVFrame * gpuFrame = nullptr;
  426 +
  427 + bool bFirst = true;
  428 + while(true){
  429 + m_queue_mutex.lock();
  430 + if(mFrameQueue.size() <= 0){
  431 + m_queue_mutex.unlock();
  432 + if(bFirst){
  433 + std::this_thread::sleep_for(std::chrono::milliseconds(100));
  434 + bFirst = false;
  435 + continue;
  436 + }else{
  437 + // 再进来说明前面已经等了 100 ms
  438 + // 100 ms都没有等到解码数据,则退出
  439 + return nullptr;
  440 + }
  441 + }
  442 +
  443 + // 队列中数据大于1
  444 + gpuFrame = mFrameQueue.front();
  445 + m_queue_mutex.unlock();
  446 + break;
  447 + }
  448 +
  449 + if (gpuFrame != nullptr && gpuFrame->format == AV_PIX_FMT_CUDA ){
  450 + LOG_DEBUG("decode task: gpuid: {} width: {} height: {}", m_cfg.gpuid, gpuFrame->width, gpuFrame->height);
  451 + GpuRgbMemory* gpuMem = new GpuRgbMemory(3, gpuFrame->width, gpuFrame->height, getName(), m_cfg.gpuid , false, true);
  452 +
  453 + if (gpuMem->getMem() == nullptr){
  454 + LOG_ERROR("new GpuRgbMemory failed !!!");
  455 + return nullptr;
  456 + }
  457 +
  458 + cudaSetDevice(atoi(m_cfg.gpuid.c_str()));
  459 + cuda_common::setColorSpace( ITU_709, 0 );
  460 + cudaError_t cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], gpuMem->getMem(), gpuFrame->width, gpuFrame->height);
  461 + cudaDeviceSynchronize();
  462 + if (cudaStatus != cudaSuccess) {
  463 + LOG_ERROR("CUDAToBGR failed failed !!!");
  464 + return nullptr;
  465 + }
  466 +
  467 + unsigned char * pHwRgb = gpuMem->getMem();
  468 + int channel = gpuMem->getChannel();
  469 + int width = gpuMem->getWidth();
  470 + int height = gpuMem->getHeight();
  471 +
  472 + if (pHwRgb != nullptr && channel > 0 && width > 0 && height > 0){
  473 + int nSize = channel * height * width;
  474 +
  475 + LOG_INFO("channel:{} height:{} width:{}", channel, height, width);
  476 + // unsigned char* cpu_data = new unsigned char[nSize];
  477 +
  478 + unsigned char* cpu_data = (unsigned char *)av_malloc(nSize * sizeof(unsigned char));
  479 +
  480 + cudaMemcpy(cpu_data, pHwRgb, nSize * sizeof(unsigned char), cudaMemcpyDeviceToHost);
  481 + cudaDeviceSynchronize();
  482 +
  483 + delete gpuMem;
  484 + gpuMem = nullptr;
  485 +
  486 + FFImgInfo* imgInfo = new FFImgInfo();
  487 + imgInfo->dec_name = m_dec_name;
  488 + imgInfo->pData = cpu_data;
  489 + imgInfo->height = height;
  490 + imgInfo->width = width;
  491 + imgInfo->timestamp = UtilTools::get_cur_time_ms();
  492 + imgInfo->index = m_index;
  493 +
  494 + m_index++;
  495 +
  496 + return imgInfo;
  497 + }
  498 +
  499 + delete gpuMem;
  500 + gpuMem = nullptr;
  501 + }
  502 +
  503 + return nullptr;
376 504 }
377 505 \ No newline at end of file
... ...
src/gb28181/FFGB28181Decoder.h
... ... @@ -3,7 +3,8 @@
3 3  
4 4 #include "RTPReceiver.h"
5 5  
6   -#include "../AbstractDecoder.h"
  6 +#include "common_header.h"
  7 +#include "../interface/AbstractDecoder.h"
7 8  
8 9 #include <atomic>
9 10 #include <mutex>
... ... @@ -14,6 +15,7 @@ struct AVCodec;
14 15 struct AVFrame;
15 16 struct AVPacket;
16 17 struct SwsContext;
  18 +struct AVDictionary;
17 19  
18 20 using namespace std;
19 21  
... ... @@ -44,12 +46,31 @@ public:
44 46  
45 47 DECODER_TYPE getDecoderType(){ return DECODER_TYPE_GB28181; }
46 48  
  49 + FFImgInfo* snapshot();
  50 +
  51 + void setName(string nm){
  52 + m_dec_name = nm;
  53 + }
  54 +
  55 + string getName(){
  56 + return m_dec_name;
  57 + }
  58 +
  59 + void setPostDecArg(const void* postDecArg);
  60 + void setFinishedDecArg(const void* finishedDecArg);
  61 +
47 62 public:
48 63 void stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts);
49 64 void stream_end_callback();
50 65 void post_decode_thread();
51 66  
52 67 private:
  68 + DeviceRgbMemory* convert2bgr(AVFrame * gpuFrame);
  69 +
  70 +private:
  71 + string m_dec_name;
  72 + FFDecConfig m_cfg;
  73 +
53 74 AVCodecContext* m_pAVCodecCtx {};
54 75 const AVCodec* m_pAVCodec {};
55 76  
... ... @@ -74,6 +95,17 @@ private:
74 95 AVDictionary *gpu_options = nullptr;
75 96  
76 97 pthread_t m_post_decode_thread;
  98 + const void * m_postDecArg;
  99 + POST_DECODE_CALLBACK post_decoded_cbk; // 解码数据回调接口
  100 +
  101 + const void * m_finishedDecArg;
  102 + DECODE_FINISHED_CALLBACK decode_finished_cbk;
  103 +
  104 + queue<AVFrame*> mFrameQueue;
  105 + mutex m_queue_mutex;
  106 + mutex m_snapshot_mutex;
  107 +
  108 + bool m_dec_keyframe;
77 109 };
78 110  
79 111 #endif // _GB28181_DECODER_H_
... ...
src/gb28181/Makefile 0 → 100644
  1 +# 各项目录
  2 +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib
  3 +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep
  4 +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj
  5 +SRC_DIR:=$(TOP_DIR)/$(MODULE)
  6 +
  7 +# 源文件以及中间目标文件和依赖文件
  8 +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp))
  9 +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS)))
  10 +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS)))
  11 +
  12 +# 自动生成头文件依赖选项
  13 +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
  14 +
  15 +JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export
  16 +
  17 +INCLUDE= -I $(TOP_DIR)/common/inc \
  18 + -I $(TOP_DIR)/common/UtilNPP \
  19 + -I $(TOP_DIR)/ \
  20 + -I $(CUDA_ROOT)/include \
  21 + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \
  22 + -I $(JRTP_ROOT)/jthread/include/jthread
  23 +
  24 +LIBSPATH= -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \
  25 + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \
  26 + -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \
  27 +
  28 +
  29 +CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(INCS) $(LIBS) $(LIBSPATH) $(MACROS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl -Wwrite-strings
  30 +
  31 +# 最终目标文件
  32 +TARGET:=$(LIB_DIR)/$(MODULE).a
  33 +
  34 +# 默认最终目标
  35 +.PHONY:all
  36 +all:$(TARGET)
  37 +
  38 +# 生成最终目标
  39 +$(TARGET):$(OBJS) | $(LIB_DIR)
  40 + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m"
  41 + @echo -e "ar -rc $@ $^"
  42 + @ar -rc $@ $^
  43 +
  44 +# 若没有lib目录则自动生成
  45 +$(LIB_DIR):
  46 + @mkdir -p $@
  47 +
  48 +# 生成中间目标文件
  49 +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR)
  50 + @echo -e "\e[33m""Building object $@""\e[0m"
  51 + @echo -e "$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<"
  52 + @$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<
  53 +
  54 +# 若没有obj目录则自动生成
  55 +$(OBJ_DIR):
  56 + @mkdir -p $@
  57 +
  58 +# 若没有.dep目录则自动生成
  59 +$(DEP_DIR):
  60 + @mkdir -p $@
  61 +
  62 +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错
  63 +$(DEPS):
  64 +
  65 +# 引入中间目标文件头文件依赖关系
  66 +include $(wildcard $(DEPS))
  67 +
  68 +# 直接删除组件build目录
  69 +.PHONY:clean
  70 +clean:
  71 + @rm -rf $(BUILD_DIR)/$(MODULE)
... ...
src/gb28181/common_header.h
... ... @@ -2,7 +2,7 @@
2 2 #define _COMMON_HEADER_H_
3 3  
4 4  
5   -#include "../logger.hpp"
6   -#include "../utiltools.hpp"
  5 +#include "../interface/logger.hpp"
  6 +#include "../interface/utiltools.hpp"
7 7  
8 8 #endif
9 9 \ No newline at end of file
... ...
src/interface/AbstractDecoder.cpp 0 → 100644
  1 +#include "AbstractDecoder.h"
  2 +
  3 +#include "logger.hpp"
  4 +#include "utiltools.hpp"
  5 +
  6 +
  7 +bool AbstractDecoder::isSnapTime(){
  8 + if(m_snap_time_interval <= 0){
  9 + return false;
  10 + }
  11 + long cur_time = UtilTools::get_cur_time_ms();
  12 + if(cur_time - m_last_snap_time > m_snap_time_interval){
  13 + return true;
  14 + }
  15 + return false;
  16 +}
  17 +
  18 +void AbstractDecoder::updateLastSnapTime(){
  19 + m_last_snap_time = UtilTools::get_cur_time_ms();
  20 +}
  21 +
  22 +void AbstractDecoder::setSnapTimeInterval(long interval){
  23 + m_snap_time_interval = interval;
  24 + m_last_snap_time = UtilTools::get_cur_time_ms();
  25 +}
0 26 \ No newline at end of file
... ...
src/interface/AbstractDecoder.h 0 → 100644
  1 +#ifndef _ABSTRACT_DECODER_H_
  2 +#define _ABSTRACT_DECODER_H_
  3 +
  4 +#include "interface_headers.h"
  5 +
  6 +using namespace std;
  7 +
  8 +class AbstractDecoder{
  9 +public:
  10 + virtual ~AbstractDecoder(){};
  11 + virtual bool init(FFDecConfig& cfg) = 0;
  12 + virtual void close() = 0;
  13 + virtual bool start() = 0;
  14 + virtual void pause() = 0;
  15 + virtual void resume() = 0;
  16 +
  17 + virtual void setDecKeyframe(bool bKeyframe) = 0;
  18 +
  19 + virtual bool isRunning() = 0;
  20 + virtual bool isFinished() = 0;
  21 + virtual bool isPausing() = 0;
  22 + virtual bool getResolution( int &width, int &height ) = 0;
  23 +
  24 + virtual bool isSurport(FFDecConfig& cfg) = 0;
  25 +
  26 + virtual int getCachedQueueLength() = 0;
  27 +
  28 + virtual float fps() = 0;
  29 +
  30 + virtual DECODER_TYPE getDecoderType() = 0;
  31 +
  32 + virtual FFImgInfo* snapshot() = 0;
  33 +
  34 + virtual void setName(string nm) = 0;
  35 +
  36 + virtual string getName() = 0;
  37 +
  38 + virtual void setPostDecArg(const void* postDecArg) = 0;
  39 + virtual void setFinishedDecArg(const void* finishedDecArg) = 0;
  40 +
  41 +public:
  42 + bool isSnapTime();
  43 +
  44 + void updateLastSnapTime();
  45 +
  46 + void setSnapTimeInterval(long interval);
  47 +
  48 +public:
  49 + long m_snap_time_interval{-1};
  50 + long m_last_snap_time;
  51 + long m_index{0};
  52 +};
  53 +
  54 +#endif // _ABSTRACT_DECODER_H_
0 55 \ No newline at end of file
... ...
src/GpuRgbMemory.hpp renamed to src/interface/DeviceRgbMemory.hpp
  1 +#ifndef __DEVICE_RGB_MEMORY_H__
  2 +#define __DEVICE_RGB_MEMORY_H__
  3 +
1 4 #include<string>
2 5  
3   -#include "cuda_kernels.h"
4   -#include "define.hpp"
5 6 #include "utiltools.hpp"
6 7  
7 8 using namespace std;
8 9  
9   -class GpuRgbMemory{
  10 +class DeviceRgbMemory{
10 11  
11 12 public:
12   - GpuRgbMemory(int _channel, int _width, int _height, string _id, string _gpuid, bool _isused){
  13 + DeviceRgbMemory(int _channel, int _width, int _height, string _id, string _dev_id, bool _key_frame, bool _isused){
13 14 channel = _channel;
14 15 width = _width;
15 16 height = _height;
16   - size = channel * width * height;
  17 + data_size = channel * width * height;
17 18 isused = _isused;
18 19 id = _id;
19   - gpuid = _gpuid;
  20 + device_id = _dev_id;
  21 + key_frame = _key_frame;
20 22 timestamp = UtilTools::get_cur_time_ms();
21   -
22   - cudaSetDevice(atoi(gpuid.c_str()));
23   - CHECK_CUDA(cudaMalloc((void **)&pHwRgb, size * sizeof(unsigned char)));
24 23 }
25 24  
26   - ~GpuRgbMemory(){
27   - if (pHwRgb) {
28   - cudaSetDevice(atoi(gpuid.c_str()));
29   - CHECK_CUDA(cudaFree(pHwRgb));
30   - pHwRgb = nullptr;
31   - }
32   - }
  25 + virtual ~DeviceRgbMemory(){}
33 26  
34 27 int getSize() {
35   - return size;
  28 + return data_size;
36 29 }
37 30  
38 31 bool isIsused() {
... ... @@ -49,8 +42,8 @@ public:
49 42 return id;
50 43 }
51 44  
52   - string getGpuId() {
53   - return gpuid;
  45 + string getDeviceId() {
  46 + return device_id;
54 47 }
55 48  
56 49 unsigned char* getMem(){
... ... @@ -73,14 +66,21 @@ public:
73 66 return channel;
74 67 }
75 68  
76   -private:
77   - int size;
  69 + bool isKeyFrame(){
  70 + return key_frame;
  71 + }
  72 +
  73 +public:
  74 + int data_size;
78 75 bool isused;
79 76 string id;
80   - string gpuid;
  77 + string device_id;
81 78 unsigned char * pHwRgb{nullptr};
82 79 long long timestamp;
83 80 int width{0};
84 81 int height{0};
85 82 int channel{3};
86   -};
87 83 \ No newline at end of file
  84 + bool key_frame;
  85 +};
  86 +
  87 +#endif
88 88 \ No newline at end of file
... ...
src/FFNvDecoderManager.cpp renamed to src/interface/FFNvDecoderManager.cpp
1 1 #include "FFNvDecoderManager.h"
2 2  
3   -#include "FFNvDecoder.h"
4   -#include "./gb28181/FFGB28181Decoder.h"
  3 +#ifdef USE_NVDEC
  4 +#include "../nvdec/FFNvDecoder.h"
  5 +#include "../gb28181/FFGB28181Decoder.h"
  6 +#endif
  7 +
  8 +#ifdef USE_DVPP
  9 +#include "./dvpp/DvppDecoderApi.h"
  10 +#endif
5 11  
6 12 #include "logger.hpp"
7 13  
... ... @@ -25,22 +31,31 @@ AbstractDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){
25 31 }
26 32  
27 33 AbstractDecoder* dec = nullptr;
  34 +#ifdef USE_NVDEC
28 35 if(DECODER_TYPE_FFMPEG == config.dec_type){
29 36 dec = new FFNvDecoder();
30   - }else if(DECODER_TYPE_GB28181 == config.dec_type){
  37 + }
  38 +
  39 + if(DECODER_TYPE_GB28181 == config.dec_type){
31 40 dec = new FFGB28181Decoder();
32 41 }
  42 +#endif
  43 +
  44 +#ifdef USE_DVPP
  45 + if(DECODER_TYPE_DVPP == config.dec_type){
  46 + dec = new DvppDecoderApi();
  47 + }
  48 +#endif
33 49  
34 50 if (dec == nullptr){
35 51 LOG_ERROR("没有指定解码器类型");
36 52 return nullptr;
37 53 }
38 54  
  55 + config.cfg.dec_name = config.name;
39 56 bool bRet= dec->init(config.cfg);
40 57 if (bRet)
41 58 {
42   - dec->setName(config.name) ;
43   - dec->setSnapTimeInterval(config.snap_time_interval);
44 59 decoderMap[config.name] = dec;
45 60  
46 61 LOG_INFO("[{}][{}]- 解码器初始化成功",config.name, config.cfg.uri);
... ... @@ -68,7 +83,7 @@ bool FFNvDecoderManager::setPostDecArg(const string name, const void * userPtr)
68 83 auto dec = decoderMap.find(name);
69 84 if (dec != decoderMap.end())
70 85 {
71   - dec->second->m_postDecArg = userPtr;
  86 + dec->second->setPostDecArg(userPtr);
72 87 return true;
73 88 }
74 89  
... ... @@ -89,7 +104,7 @@ bool FFNvDecoderManager::setFinishedDecArg(const string name, const void * userP
89 104 auto dec = decoderMap.find(name);
90 105 if (dec != decoderMap.end())
91 106 {
92   - dec->second->m_finishedDecArg = userPtr;
  107 + dec->second->setFinishedDecArg(userPtr);
93 108 return true;
94 109 }
95 110  
... ... @@ -273,11 +288,21 @@ bool FFNvDecoderManager::isSurport(MgrDecConfig&amp; config)
273 288 }
274 289  
275 290 AbstractDecoder* dec = nullptr;
276   - if(config.dec_type = DECODER_TYPE_FFMPEG){
  291 +#ifdef USE_NVDEC
  292 + if(DECODER_TYPE_FFMPEG == config.dec_type){
277 293 dec = new FFNvDecoder();
278   - }else if(config.dec_type = DECODER_TYPE_GB28181){
  294 + }
  295 +
  296 + if(DECODER_TYPE_GB28181 == config.dec_type){
279 297 dec = new FFGB28181Decoder();
280 298 }
  299 +#endif
  300 +
  301 +#ifdef USE_DVPP
  302 + if(DECODER_TYPE_DVPP == config.dec_type){
  303 + dec = new DvppDecoderApi();
  304 + }
  305 +#endif
281 306  
282 307 if (dec == nullptr){
283 308 LOG_ERROR("没有指定解码器类型");
... ... @@ -420,142 +445,10 @@ int FFNvDecoderManager::getCachedQueueLength(const string name){
420 445 return -1;
421 446 }
422 447  
423   -FFImgInfo* FFNvDecoderManager::snapshot(const string& uri){
424   - if (uri.empty()){
425   - return nullptr;
426   - }
427   -
428   - AVFormatContext* ifmt_ctx = nullptr;
429   - AVCodecContext* codec_ctx = nullptr;
430   - AVCodec* codec = nullptr;
431   - AVPacket* pkt = nullptr;
432   - AVFrame *frame = nullptr;
433   - AVFrame *pFrameRGB = nullptr;
434   - int video_index = -1;
435   - AVStream* st = nullptr;
436   - SwsContext *img_convert_ctx = nullptr;
437   - uint8_t *buffer = nullptr;
438   - int numBytes = 0;
439   - int index = 0;
440   -
441   - FFImgInfo* imgInfo = nullptr;
442   -
443   - //av_register_all();
444   - avformat_network_init();
445   -
446   - // 参数设置
447   - AVDictionary *options = nullptr;
448   - av_dict_set( &options, "bufsize", "655360", 0 );
449   - av_dict_set( &options, "rtsp_transport", "tcp", 0 );
450   - av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
451   -
452   - ///打开输入的流
453   - int ret = avformat_open_input(&ifmt_ctx, uri.c_str(), nullptr, &options);
454   - if (ret != 0){
455   - printf("Couldn't open input stream.\n");
456   - goto end_flag ;
457   - }
458   -
459   - //查找流信息
460   - if (avformat_find_stream_info(ifmt_ctx, nullptr) < 0){
461   - printf("Couldn't find stream information.\n");
462   - goto end_flag ;
463   - }
464   -
465   - //找到视频流索引
466   - video_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
467   -
468   - st = ifmt_ctx->streams[video_index];
469   -
470   - //找到解码器
471   - codec = avcodec_find_decoder(st->codecpar->codec_id);
472   - if (!codec){
473   - fprintf(stderr, "Codec not found\n");
474   - goto end_flag ;
475   - }
476   -
477   - //申请AVCodecContext
478   - codec_ctx = avcodec_alloc_context3(codec);
479   - if (!codec_ctx){
480   - goto end_flag ;
481   - }
482   -
483   - avcodec_parameters_to_context(codec_ctx, ifmt_ctx->streams[video_index]->codecpar);
484   -
485   - //打开解码器
486   - if ((ret = avcodec_open2(codec_ctx, codec, nullptr) < 0)){
487   - goto end_flag ;
488   - }
489   -
490   - // 计算解码后原始数据所需缓冲区大小,并分配内存空间 Determine required buffer size and allocate buffer
491   - numBytes = av_image_get_buffer_size(AV_PIX_FMT_BGR24, codec_ctx->width, codec_ctx->height, 1);
492   - buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
493   -
494   - pFrameRGB = av_frame_alloc();
495   - av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_BGR24, codec_ctx->width, codec_ctx->height, 1);
496   -
497   - img_convert_ctx = sws_getContext(codec_ctx->width, codec_ctx->height,codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_BGR24,
498   - SWS_BICUBIC, nullptr, nullptr, nullptr);
499   -
500   - pkt = av_packet_alloc();
501   - frame = av_frame_alloc();
502   - while (av_read_frame(ifmt_ctx, pkt) >= 0){
503   - if (pkt->stream_index == video_index){
504   - int ret = avcodec_send_packet(codec_ctx, pkt);
505   - if (ret >= 0){
506   - ret = avcodec_receive_frame(codec_ctx, frame);
507   - if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){
508   - LOG_ERROR("Failed to receive frame: {}",ret);
509   - continue;
510   - }
511   -
512   - index ++ ;
513   -
514   - if (index >= 5){
515   - // 取解码出来的第三帧,应该可以一定程度优化花屏问题
516   - sws_scale(img_convert_ctx, (const unsigned char* const*)frame->data, frame->linesize, 0, codec_ctx->height, pFrameRGB->data, pFrameRGB->linesize);
517   -
518   - imgInfo = new FFImgInfo();
519   - imgInfo->pData = buffer;
520   - imgInfo->height = codec_ctx->height;
521   - imgInfo->width = codec_ctx->width;
522   -
523   - break;
524   - }
525   - }
526   - }
527   - av_packet_unref(pkt);
528   - }
529   -
530   -end_flag:
531   - if (codec_ctx != nullptr){
532   - avcodec_close(codec_ctx);
533   - avcodec_free_context(&codec_ctx);
534   - }
535   -
536   - if (ifmt_ctx != nullptr){
537   - avformat_close_input(&ifmt_ctx);
538   - }
539   -
540   - if (frame != nullptr){
541   - av_frame_free(&frame);
542   - }
543   -
544   - if (pFrameRGB != nullptr){
545   - av_frame_free(&pFrameRGB);
546   - }
547   -
548   - if (pkt != nullptr){
549   - av_packet_free(&pkt);
550   - }
551   -
552   - return imgInfo;
553   -}
554   -
555 448 void FFNvDecoderManager::releaseFFImgInfo(FFImgInfo* info){
556 449 if(nullptr != info){
557 450 if(info->pData != nullptr){
558   - av_free(info->pData);
  451 + free(info->pData);
559 452 info->pData = nullptr;
560 453 }
561 454 delete info;
... ...
src/FFNvDecoderManager.h renamed to src/interface/FFNvDecoderManager.h
... ... @@ -15,6 +15,8 @@ struct MgrDecConfig
15 15 long snap_time_interval; // 定时抓拍时间间隔
16 16 };
17 17  
  18 +// #define USE_NVDEC
  19 +// #define USE_DVPP
18 20 /**
19 21 * 解码器管理类,单例类
20 22 * 谨防死锁
... ... @@ -236,15 +238,6 @@ public:
236 238 int getCachedQueueLength(const string name);
237 239  
238 240 /**************************************************
239   - * 接口:snapshot
240   - * 功能:获取视频快照
241   - * 参数:const string& uri 视频地址
242   - * 返回:FFImgInfo* 快照信息
243   - * 备注:
244   - **************************************************/
245   - FFImgInfo* snapshot(const string& uri);
246   -
247   - /**************************************************
248 241 * 接口:releaseFFImgInfo
249 242 * 功能:释放视频快照信息
250 243 * 参数:FFImgInfo* info 视频快照信息
... ...
src/interface/Makefile 0 → 100644
  1 +# 各项目录
  2 +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib
  3 +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep
  4 +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj
  5 +SRC_DIR:=$(TOP_DIR)/$(MODULE)
  6 +
  7 +# 源文件以及中间目标文件和依赖文件
  8 +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp))
  9 +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS)))
  10 +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS)))
  11 +
  12 +# 自动生成头文件依赖选项
  13 +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
  14 +
  15 +JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export
  16 +
  17 +INCLUDE= -I $(TOP_DIR)/common/inc \
  18 + -I $(TOP_DIR)/common/UtilNPP \
  19 + -I $(TOP_DIR)/ \
  20 + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \
  21 + -I $(JRTP_ROOT)/jthread/include/jthread \
  22 + -I $(TOP_DIR)/src/gb28181 \
  23 + -I $(TOP_DIR)/src/nvdec \
  24 + -I $(CUDA_ROOT)/include \
  25 +
  26 +LIBSPATH= -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \
  27 + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \
  28 + -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \
  29 +
  30 +
  31 +CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(LIBSPATH) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl -Wwrite-strings
  32 +
  33 +
  34 +# 最终目标文件
  35 +TARGET:=$(LIB_DIR)/$(MODULE).a
  36 +
  37 +
  38 +# 默认最终目标
  39 +.PHONY:all
  40 +all:$(TARGET)
  41 +
  42 +# 生成最终目标
  43 +$(TARGET):$(OBJS) | $(LIB_DIR)
  44 + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m"
  45 + @echo -e "ar -rc $@ $^"
  46 + @ar -rc $@ $^
  47 +
  48 +# 若没有lib目录则自动生成
  49 +$(LIB_DIR):
  50 + @mkdir -p $@
  51 +
  52 +# 生成中间目标文件
  53 +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR)
  54 + @echo -e "\e[33m""Building object $@""\e[0m"
  55 + @echo -e "$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) $(INCS) $(LIBS) $(MACROS) -o $@ $<"
  56 +# @$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) $(INCS) $(LIBSPATH) $(MACROS) -o $@ $(MODULE_LIBS) $<
  57 + @$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) $(INCS) $(LIBS) $(MACROS) -o $@ $<
  58 +
  59 +# 若没有obj目录则自动生成
  60 +$(OBJ_DIR):
  61 + @mkdir -p $@
  62 +
  63 +# 若没有.dep目录则自动生成
  64 +$(DEP_DIR):
  65 + @mkdir -p $@
  66 +
  67 +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错
  68 +$(DEPS):
  69 +
  70 +# 引入中间目标文件头文件依赖关系
  71 +include $(wildcard $(DEPS))
  72 +
  73 +# 直接删除组件build目录
  74 +.PHONY:clean
  75 +clean:
  76 + @rm -rf $(BUILD_DIR)/$(MODULE)
... ...
src/AbstractDecoder.h renamed to src/interface/interface_headers.h
1   -#ifndef _ABSTRACT_DECODER_H_
2   -#define _ABSTRACT_DECODER_H_
  1 +#ifndef _INTERFACE_HEADERS_H_
  2 +#define _INTERFACE_HEADERS_H_
3 3  
4   -#include<string>
5   -
6   -extern "C"
7   -{
8   - #include <libavcodec/avcodec.h>
9   - #include <libavdevice/avdevice.h>
10   - #include <libavformat/avformat.h>
11   - #include <libavfilter/avfilter.h>
12   - #include <libavutil/avutil.h>
13   - #include <libavutil/pixdesc.h>
14   - #include <libswscale/swscale.h>
15   - #include <libavutil/imgutils.h>
16   -}
17 4  
  5 +#include<string>
18 6 #include <queue>
19 7 #include <mutex>
20 8  
  9 +#include "DeviceRgbMemory.hpp"
  10 +
21 11 using namespace std;
22 12  
23 13 /**************************************************
... ... @@ -31,7 +21,7 @@ using namespace std;
31 21 * 非实时流时(本地/网络文件),本接口可以进行
32 22 * 阻塞/耗时操作
33 23 **************************************************/
34   -typedef void(*POST_DECODE_CALLBACK)(const void * userPtr, AVFrame * gpuFrame);
  24 +typedef void(*POST_DECODE_CALLBACK)(const void * userPtr, DeviceRgbMemory* devFrame);
35 25  
36 26 typedef void(*DECODE_FINISHED_CALLBACK)(const void* userPtr);
37 27  
... ... @@ -44,6 +34,7 @@ struct FFDecConfig{
44 34 string gpuid; // gpu id
45 35 bool force_tcp{true}; // 是否指定使用tcp连接
46 36 int skip_frame{1}; // 跳帧数
  37 + string dec_name;
47 38  
48 39 int port; // gb28181接收数据的端口号
49 40 DECODE_REQUEST_STREAM_CALLBACK request_stream_cbk; // gb28181请求流
... ... @@ -51,7 +42,8 @@ struct FFDecConfig{
51 42  
52 43 enum DECODER_TYPE{
53 44 DECODER_TYPE_GB28181,
54   - DECODER_TYPE_FFMPEG
  45 + DECODER_TYPE_FFMPEG,
  46 + DECODER_TYPE_DVPP
55 47 };
56 48  
57 49 struct FFImgInfo{
... ... @@ -59,70 +51,9 @@ struct FFImgInfo{
59 51 int width;
60 52 int height;
61 53 unsigned char * pData;
  54 + int data_type; // 默认0=rgb, 1=nv12
62 55 long timestamp;
63 56 long index;
64 57 };
65 58  
66   -class AbstractDecoder {
67   -public:
68   - virtual ~AbstractDecoder(){};
69   - virtual bool init(FFDecConfig& cfg) = 0;
70   - virtual void close() = 0;
71   - virtual bool start() = 0;
72   - virtual void pause() = 0;
73   - virtual void resume() = 0;
74   -
75   - virtual void setDecKeyframe(bool bKeyframe) = 0;
76   -
77   - virtual bool isRunning() = 0;
78   - virtual bool isFinished() = 0;
79   - virtual bool isPausing() = 0;
80   - virtual bool getResolution( int &width, int &height ) = 0;
81   -
82   - virtual bool isSurport(FFDecConfig& cfg) = 0;
83   -
84   - virtual int getCachedQueueLength() = 0;
85   -
86   - virtual float fps() = 0;
87   -
88   - virtual DECODER_TYPE getDecoderType() = 0;
89   -
90   - void setName(string nm){
91   - m_dec_name = nm;
92   - }
93   -
94   - string getName(){
95   - return m_dec_name;
96   - }
97   -
98   - FFImgInfo* snapshot();
99   -
100   - bool isSnapTime();
101   -
102   - void updateLastSnapTime();
103   -
104   - void setSnapTimeInterval(long interval);
105   -
106   -public:
107   - const void * m_postDecArg;
108   - POST_DECODE_CALLBACK post_decoded_cbk;
109   - const void * m_finishedDecArg;
110   - DECODE_FINISHED_CALLBACK decode_finished_cbk;
111   -
112   -public:
113   - string m_dec_name;
114   -
115   - bool m_dec_keyframe;
116   -
117   - FFDecConfig m_cfg;
118   -
119   - queue<AVFrame*> mFrameQueue;
120   - mutex m_queue_mutex;
121   - mutex m_snapshot_mutex;
122   -
123   - long m_snap_time_interval{-1};
124   - long m_last_snap_time;
125   - long m_index{0};
126   -};
127   -
128   -#endif // _ABSTRACT_DECODER_H_
129 59 \ No newline at end of file
  60 +#endif
130 61 \ No newline at end of file
... ...
src/logger.hpp renamed to src/interface/logger.hpp
... ... @@ -8,7 +8,7 @@
8 8  
9 9 #pragma once
10 10  
11   -#include "define.hpp"
  11 +// #include "define.hpp"
12 12 #include <spdlog/spdlog.h>
13 13 #include <spdlog/common.h>
14 14 #include <spdlog/details/file_helper.h>
... ... @@ -28,6 +28,8 @@
28 28 #include <memory>
29 29 #include <vector>
30 30  
  31 +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
  32 +
31 33 #define LOG_TRACE_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_TRACE(logger, __VA_ARGS__);}
32 34 #define LOG_DEBUG_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_DEBUG(logger, __VA_ARGS__);}
33 35 #define LOG_WARN_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_WARN(logger, __VA_ARGS__);}
... ...
src/utiltools.hpp renamed to src/interface/utiltools.hpp
1 1 #ifndef _UTIL_TOOLS_HPP_
2 2 #define _UTIL_TOOLS_HPP_
3 3  
4   -#include<chrono>
  4 +#include <chrono>
5 5  
6 6 using namespace std;
7 7  
... ...
src/DrawImageOnGPU.cu renamed to src/nvdec/DrawImageOnGPU.cu
1 1 #include "cuda_kernels.h"
2 2  
3   -#include "logger.hpp"
  3 +#include "../interface/logger.hpp"
4 4  
5 5 typedef unsigned char uchar;
6 6 typedef unsigned int uint32;
... ...
src/FFCuContextManager.cpp renamed to src/nvdec/FFCuContextManager.cpp
1 1 #include "FFCuContextManager.h"
2 2  
3   -#include "logger.hpp"
  3 +#include "common_header.h"
4 4  
5 5 using namespace std;
6 6  
  7 +extern "C"
  8 +{
  9 + #include <libavcodec/avcodec.h>
  10 + #include <libavdevice/avdevice.h>
  11 + #include <libavformat/avformat.h>
  12 + #include <libavfilter/avfilter.h>
  13 + #include <libavutil/avutil.h>
  14 + #include <libavutil/pixdesc.h>
  15 + #include <libswscale/swscale.h>
  16 + #include <libavutil/imgutils.h>
  17 +}
  18 +
7 19 FFCuContextManager::~FFCuContextManager()
8 20 {
9 21 for(auto iter = ctxMap.begin(); iter != ctxMap.end(); iter++){
... ...
src/FFCuContextManager.h renamed to src/nvdec/FFCuContextManager.h
... ... @@ -2,19 +2,10 @@
2 2 #include<map>
3 3 #include<string>
4 4  
5   -extern "C"
6   -{
7   - #include <libavcodec/avcodec.h>
8   - #include <libavdevice/avdevice.h>
9   - #include <libavformat/avformat.h>
10   - #include <libavfilter/avfilter.h>
11   - #include <libavutil/avutil.h>
12   - #include <libavutil/pixdesc.h>
13   - #include <libswscale/swscale.h>
14   -}
15   -
16 5 using namespace std;
17 6  
  7 +struct AVBufferRef;
  8 +
18 9 class FFCuContextManager{
19 10 public:
20 11 static FFCuContextManager* getInstance(){
... ...
src/FFNvDecoder.cpp renamed to src/nvdec/FFNvDecoder.cpp
... ... @@ -8,9 +8,10 @@
8 8  
9 9 #include "FFCuContextManager.h"
10 10  
11   -#include "logger.hpp"
  11 +#include "common_header.h"
12 12  
13   -#include "utiltools.hpp"
  13 +#include "GpuRgbMemory.hpp"
  14 +#include "cuda_kernels.h"
14 15  
15 16 using namespace std;
16 17  
... ... @@ -62,6 +63,7 @@ FFNvDecoder::~FFNvDecoder()
62 63 bool FFNvDecoder::init(FFDecConfig& cfg)
63 64 {
64 65 m_cfg = cfg;
  66 + m_dec_name = cfg.dec_name;
65 67  
66 68 fstream infile(cfg.uri);
67 69 if (infile.is_open()){
... ... @@ -217,16 +219,6 @@ void FFNvDecoder::decode_thread()
217 219 continue;
218 220 }
219 221  
220   - if (m_bReal)
221   - {
222   - if (m_bPause)
223   - {
224   - av_packet_unref(pkt);
225   - std::this_thread::sleep_for(std::chrono::milliseconds(3));
226   - continue;
227   - }
228   - }
229   -
230 222 if (stream_index == pkt->stream_index){
231 223 result = avcodec_send_packet(avctx, pkt);
232 224 if (result < 0){
... ... @@ -245,6 +237,14 @@ void FFNvDecoder::decode_thread()
245 237 }
246 238 av_packet_unref(pkt);
247 239  
  240 + if (m_bReal){
  241 + if (m_bPause){
  242 + av_frame_free(&gpuFrame);
  243 + std::this_thread::sleep_for(std::chrono::milliseconds(3));
  244 + continue;
  245 + }
  246 + }
  247 +
248 248 if(gpuFrame != nullptr){
249 249 m_queue_mutex.lock();
250 250 if(mFrameQueue.size() <= 10){
... ... @@ -259,6 +259,7 @@ void FFNvDecoder::decode_thread()
259 259 }
260 260  
261 261 m_bRunning = false;
  262 + av_packet_free(&pkt);
262 263  
263 264 // long end_time = UtilTools::get_cur_time_ms();
264 265 // cout << "解码用时:" << end_time - start_time << endl;
... ... @@ -315,7 +316,7 @@ void FFNvDecoder::post_decode_thread(){
315 316 m_queue_mutex.unlock();
316 317 // 跳帧
317 318 if (skip_frame == 1 || index % skip_frame == 0){
318   - post_decoded_cbk(m_postDecArg, gpuFrame);
  319 + post_decoded_cbk(m_postDecArg, convert2bgr(gpuFrame));
319 320 index = 0;
320 321 }
321 322  
... ... @@ -386,3 +387,127 @@ int FFNvDecoder::getCachedQueueLength(){
386 387 float FFNvDecoder::fps(){
387 388 return m_fps;
388 389 }
  390 +
  391 +void FFNvDecoder::setPostDecArg(const void* postDecArg){
  392 + m_postDecArg = postDecArg;
  393 +}
  394 +
  395 +void FFNvDecoder::setFinishedDecArg(const void* finishedDecArg){
  396 + m_finishedDecArg = finishedDecArg;
  397 +}
  398 +
  399 +DeviceRgbMemory* FFNvDecoder::convert2bgr(AVFrame * gpuFrame){
  400 + if (gpuFrame != nullptr && gpuFrame->format == AV_PIX_FMT_CUDA ){
  401 + LOG_DEBUG("decode task: gpuid: {} width: {} height: {}", m_cfg.gpuid, gpuFrame->width, gpuFrame->height);
  402 + GpuRgbMemory* gpuMem = new GpuRgbMemory(3, gpuFrame->width, gpuFrame->height, getName(), m_cfg.gpuid, false, true);
  403 +
  404 + do{
  405 + if (gpuMem->getMem() == nullptr){
  406 + LOG_ERROR("new GpuRgbMemory failed !!!");
  407 + break;
  408 + }
  409 +
  410 + cudaSetDevice(atoi(m_cfg.gpuid.c_str()));
  411 + cuda_common::setColorSpace( ITU_709, 0 );
  412 + cudaError_t cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], gpuMem->getMem(), gpuFrame->width, gpuFrame->height);
  413 + cudaDeviceSynchronize();
  414 + if (cudaStatus != cudaSuccess) {
  415 + LOG_ERROR("CUDAToBGR failed failed !!!");
  416 + break;
  417 + }
  418 +
  419 + return gpuMem;
  420 + }while(0);
  421 +
  422 + delete gpuMem;
  423 + gpuMem = nullptr;
  424 + }
  425 +
  426 + return nullptr;
  427 +}
  428 +
  429 +FFImgInfo* FFNvDecoder::snapshot(){
  430 +
  431 + // 锁住停止队列消耗
  432 + std::lock_guard<std::mutex> l(m_snapshot_mutex);
  433 +
  434 + AVFrame * gpuFrame = nullptr;
  435 +
  436 + bool bFirst = true;
  437 + while(true){
  438 + m_queue_mutex.lock();
  439 + if(mFrameQueue.size() <= 0){
  440 + m_queue_mutex.unlock();
  441 + if(bFirst){
  442 + std::this_thread::sleep_for(std::chrono::milliseconds(100));
  443 + bFirst = false;
  444 + continue;
  445 + }else{
  446 + // 再进来说明前面已经等了 100 ms
  447 + // 100 ms都没有等到解码数据,则退出
  448 + return nullptr;
  449 + }
  450 + }
  451 +
  452 + // 队列中数据大于1
  453 + gpuFrame = mFrameQueue.front();
  454 + m_queue_mutex.unlock();
  455 + break;
  456 + }
  457 +
  458 + if (gpuFrame != nullptr && gpuFrame->format == AV_PIX_FMT_CUDA ){
  459 + LOG_DEBUG("decode task: gpuid: {} width: {} height: {}", m_cfg.gpuid, gpuFrame->width, gpuFrame->height);
  460 + GpuRgbMemory* gpuMem = new GpuRgbMemory(3, gpuFrame->width, gpuFrame->height, getName(), m_cfg.gpuid, false, true);
  461 +
  462 + if (gpuMem->getMem() == nullptr){
  463 + LOG_ERROR("new GpuRgbMemory failed !!!");
  464 + return nullptr;
  465 + }
  466 +
  467 + cudaSetDevice(atoi(m_cfg.gpuid.c_str()));
  468 + cuda_common::setColorSpace( ITU_709, 0 );
  469 + cudaError_t cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], gpuMem->getMem(), gpuFrame->width, gpuFrame->height);
  470 + cudaDeviceSynchronize();
  471 + if (cudaStatus != cudaSuccess) {
  472 + LOG_ERROR("CUDAToBGR failed failed !!!");
  473 + return nullptr;
  474 + }
  475 +
  476 + unsigned char * pHwRgb = gpuMem->getMem();
  477 + int channel = gpuMem->getChannel();
  478 + int width = gpuMem->getWidth();
  479 + int height = gpuMem->getHeight();
  480 +
  481 + if (pHwRgb != nullptr && channel > 0 && width > 0 && height > 0){
  482 + int nSize = channel * height * width;
  483 +
  484 + LOG_INFO("channel:{} height:{} width:{}", channel, height, width);
  485 + // unsigned char* cpu_data = new unsigned char[nSize];
  486 +
  487 + unsigned char* cpu_data = (unsigned char *)av_malloc(nSize * sizeof(unsigned char));
  488 +
  489 + cudaMemcpy(cpu_data, pHwRgb, nSize * sizeof(unsigned char), cudaMemcpyDeviceToHost);
  490 + cudaDeviceSynchronize();
  491 +
  492 + delete gpuMem;
  493 + gpuMem = nullptr;
  494 +
  495 + FFImgInfo* imgInfo = new FFImgInfo();
  496 + imgInfo->dec_name = m_dec_name;
  497 + imgInfo->pData = cpu_data;
  498 + imgInfo->height = height;
  499 + imgInfo->width = width;
  500 + imgInfo->timestamp = UtilTools::get_cur_time_ms();
  501 + imgInfo->index = m_index;
  502 +
  503 + m_index++;
  504 +
  505 + return imgInfo;
  506 + }
  507 +
  508 + delete gpuMem;
  509 + gpuMem = nullptr;
  510 + }
  511 +
  512 + return nullptr;
  513 +}
389 514 \ No newline at end of file
... ...
src/FFNvDecoder.h renamed to src/nvdec/FFNvDecoder.h
1 1 #include<string>
2 2 #include <pthread.h>
3 3  
4   -#include "AbstractDecoder.h"
5   -
6 4 #include <mutex>
7 5  
  6 +extern "C"
  7 +{
  8 + #include <libavcodec/avcodec.h>
  9 + #include <libavdevice/avdevice.h>
  10 + #include <libavformat/avformat.h>
  11 + #include <libavfilter/avfilter.h>
  12 + #include <libavutil/avutil.h>
  13 + #include <libavutil/pixdesc.h>
  14 + #include <libswscale/swscale.h>
  15 + #include <libavutil/imgutils.h>
  16 +}
  17 +
  18 +#include "common_header.h"
  19 +
  20 +#include "../interface/AbstractDecoder.h"
  21 +
8 22 using namespace std;
9 23  
10   -class FFNvDecoder : public AbstractDecoder{
  24 +class FFNvDecoder : public AbstractDecoder {
11 25 public:
12 26 FFNvDecoder();
13 27 ~FFNvDecoder();
... ... @@ -32,6 +46,19 @@ public:
32 46  
33 47 DECODER_TYPE getDecoderType(){ return DECODER_TYPE_FFMPEG; }
34 48  
  49 + FFImgInfo* snapshot();
  50 +
  51 + void setName(string nm){
  52 + m_dec_name = nm;
  53 + }
  54 +
  55 + string getName(){
  56 + return m_dec_name;
  57 + }
  58 +
  59 + void setPostDecArg(const void* postDecArg);
  60 + void setFinishedDecArg(const void* finishedDecArg);
  61 +
35 62 public:
36 63 AVPixelFormat getHwPixFmt();
37 64  
... ... @@ -41,7 +68,12 @@ private:
41 68 bool init(const char* uri, const char* gpuid, bool force_tcp);
42 69 void decode_finished();
43 70  
  71 + DeviceRgbMemory* convert2bgr(AVFrame * gpuFrame);
  72 +
44 73 private:
  74 + string m_dec_name;
  75 + FFDecConfig m_cfg;
  76 +
45 77 AVStream* stream;
46 78 AVCodecContext *avctx;
47 79 int stream_index;
... ... @@ -59,4 +91,17 @@ private:
59 91 bool m_bReal; // 是否实时流
60 92  
61 93 float m_fps;
  94 +
  95 + queue<AVFrame*> mFrameQueue;
  96 + mutex m_queue_mutex;
  97 + mutex m_snapshot_mutex;
  98 + long m_index{0};
  99 +
  100 + bool m_dec_keyframe;
  101 +
  102 + const void * m_postDecArg;
  103 + POST_DECODE_CALLBACK post_decoded_cbk; // 解码数据回调接口
  104 +
  105 + const void * m_finishedDecArg;
  106 + DECODE_FINISHED_CALLBACK decode_finished_cbk;
62 107 };
63 108 \ No newline at end of file
... ...
src/nvdec/GpuRgbMemory.hpp 0 → 100644
  1 +#include<string>
  2 +
  3 +#include "../interface/DeviceRgbMemory.hpp"
  4 +#include "cuda_kernels.h"
  5 +#include "define.hpp"
  6 +#include "common_header.h"
  7 +
  8 +using namespace std;
  9 +
  10 +class GpuRgbMemory : public DeviceRgbMemory{
  11 +
  12 +public:
  13 + GpuRgbMemory(int _channel, int _width, int _height, string _id, string _gpuid, bool _key_frame, bool _isused)
  14 + :DeviceRgbMemory(_channel, _width, _height, _id, _gpuid, _key_frame, _isused){
  15 + gpuid = _gpuid;
  16 + cudaSetDevice(atoi(gpuid.c_str()));
  17 + CHECK_CUDA(cudaMalloc((void **)&pHwRgb, data_size * sizeof(unsigned char)));
  18 + }
  19 +
  20 + ~GpuRgbMemory(){
  21 + if (pHwRgb) {
  22 + cudaSetDevice(atoi(gpuid.c_str()));
  23 + CHECK_CUDA(cudaFree(pHwRgb));
  24 + pHwRgb = nullptr;
  25 + }
  26 + }
  27 +
  28 + string getGpuId() {
  29 + return gpuid;
  30 + }
  31 +
  32 +private:
  33 + string gpuid;
  34 +};
0 35 \ No newline at end of file
... ...
src/ImageSaveGPU.cpp renamed to src/nvdec/ImageSaveGPU.cpp
1 1 #include "cuda_kernels.h"
2 2  
3   -#include "logger.hpp"
  3 +#include "common_header.h"
4 4  
5 5  
6 6 //int saveJPEG(const char *szOutputFile, float* d_srcRGB, int img_width, int img_height)
... ...
src/ImageSaveGPU.h renamed to src/nvdec/ImageSaveGPU.h
src/nvdec/Makefile 0 → 100644
  1 +# 各项目录
  2 +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib
  3 +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep
  4 +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj
  5 +SRC_DIR:=$(TOP_DIR)/$(MODULE)
  6 +
  7 +# 源文件以及中间目标文件和依赖文件
  8 +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp))
  9 +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS)))
  10 +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS)))
  11 +
  12 +
  13 +NVCC = $(CUDA_ROOT)/bin/nvcc
  14 +
  15 +# 自动生成头文件依赖选项
  16 +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d
  17 +
  18 +DEFS =
  19 +
  20 +# 最终目标文件
  21 +TARGET:=$(LIB_DIR)/$(MODULE).a
  22 +
  23 +
  24 +JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export
  25 +
  26 +INCLUDE= -I $(TOP_DIR)/common/inc \
  27 + -I $(TOP_DIR)/common/UtilNPP \
  28 + -I $(TOP_DIR) \
  29 + -I $(CUDA_ROOT)/include \
  30 + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \
  31 + -I $(JRTP_ROOT)/jthread/include/jthread
  32 +
  33 +LIBSPATH= -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \
  34 + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \
  35 + -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \
  36 +
  37 +CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(LIBSPATH) $(DEFS) $(INCS) $(LIBS) $(MACROS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl -Wwrite-strings
  38 + # -DUNICODE -D_UNICODE
  39 +
  40 +NFLAGS_LIB=-g -c -shared -Xcompiler -fPIC
  41 +NFLAGS = $(NFLAGS_LIB) $(INCLUDE) $(LIBSPATH) -std=c++11
  42 +
  43 +CU_SOURCES:=$(notdir $(wildcard $(SRC_DIR)/*.cu))
  44 +CU_OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cu, %.o, $(CU_SOURCES)))
  45 +
  46 +
  47 +# 默认最终目标
  48 +.PHONY:all
  49 +all:$(TARGET)
  50 +
  51 +# 生成最终目标
  52 +$(TARGET):$(OBJS) $(CU_OBJS) | $(LIB_DIR)
  53 + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m"
  54 + @echo -e "ar -rc $@ $^"
  55 + @ar -rc $@ $^
  56 +
  57 +# 若没有lib目录则自动生成
  58 +$(LIB_DIR):
  59 + @mkdir -p $@
  60 +
  61 +# 生成中间目标文件
  62 +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR)
  63 + @echo -e "\e[33m""Building object $@""\e[0m"
  64 + @echo "$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<"
  65 + @$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<
  66 +
  67 +$(OBJ_DIR)%.o:$(SRC_DIR)/%.cu
  68 + @echo -e "\e[33m""Building object $@""\e[0m"
  69 + @echo "$(NVCC) $(NFLAGS) $(INCS) $(LIBS) -o $@ $<"
  70 + $(NVCC) $(NFLAGS) $(INCS) $(LIBS) -o $@ $<
  71 +
  72 +
  73 +# 若没有obj目录则自动生成
  74 +$(OBJ_DIR):
  75 + @mkdir -p $@
  76 +
  77 +# 若没有.dep目录则自动生成
  78 +$(DEP_DIR):
  79 + @mkdir -p $@
  80 +
  81 +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错
  82 +$(DEPS):
  83 +
  84 +# 引入中间目标文件头文件依赖关系
  85 +include $(wildcard $(DEPS))
  86 +
  87 +# 直接删除组件build目录
  88 +.PHONY:clean
  89 +clean:
  90 + @rm -rf $(BUILD_DIR)/$(MODULE)
... ...
src/NV12ToRGB.cu renamed to src/nvdec/NV12ToRGB.cu
... ... @@ -2,7 +2,7 @@
2 2 #include "cuda_kernels.h"
3 3  
4 4 #include <builtin_types.h>
5   -#include "common/inc/helper_cuda_drvapi.h"
  5 +#include "helper_cuda_drvapi.h"
6 6  
7 7 typedef unsigned char uint8;
8 8 typedef unsigned int uint32;
... ...
src/nvdec/NvDecoderApi.cpp 0 → 100644
  1 +#include "NvDecoderApi.h"
  2 +#include "FFNvDecoder.h"
  3 +
  4 +NvDecoderApi::NvDecoderApi(){
  5 + m_pDecoder = nullptr;
  6 +}
  7 +
  8 +NvDecoderApi::~NvDecoderApi(){
  9 + if(m_pDecoder != nullptr){
  10 + delete m_pDecoder;
  11 + m_pDecoder = nullptr;
  12 + }
  13 +}
  14 +
  15 +bool NvDecoderApi::init(FFDecConfig& cfg){
  16 + m_pDecoder = new FFNvDecoder();
  17 + if(m_pDecoder != nullptr){
  18 + return m_pDecoder->init(cfg);
  19 + }
  20 + return false;
  21 +}
  22 +
  23 +void NvDecoderApi::close(){
  24 + if(m_pDecoder != nullptr){
  25 + return m_pDecoder->close();
  26 + }
  27 +}
  28 +
  29 +bool NvDecoderApi::start(){
  30 + if(m_pDecoder != nullptr){
  31 + return m_pDecoder->start();
  32 + }
  33 + return false;
  34 +}
  35 +
  36 +void NvDecoderApi::pause(){
  37 + if(m_pDecoder != nullptr){
  38 + return m_pDecoder->pause();
  39 + }
  40 +}
  41 +
  42 +void NvDecoderApi::resume(){
  43 + if(m_pDecoder != nullptr){
  44 + return m_pDecoder->resume();
  45 + }
  46 +}
  47 +
  48 +void NvDecoderApi::setDecKeyframe(bool bKeyframe){
  49 + if(m_pDecoder != nullptr){
  50 + return m_pDecoder->setDecKeyframe(bKeyframe);
  51 + }
  52 +}
  53 +
  54 +bool NvDecoderApi::isRunning(){
  55 + if(m_pDecoder != nullptr){
  56 + return m_pDecoder->isRunning();
  57 + }
  58 + return false;
  59 +}
  60 +
  61 +bool NvDecoderApi::isFinished(){
  62 + if(m_pDecoder != nullptr){
  63 + return m_pDecoder->isFinished();
  64 + }
  65 + return false;
  66 +}
  67 +
  68 +bool NvDecoderApi::isPausing(){
  69 + if(m_pDecoder != nullptr){
  70 + return m_pDecoder->isPausing();
  71 + }
  72 + return false;
  73 +}
  74 +
  75 +bool NvDecoderApi::getResolution(int &width, int &height){
  76 + if(m_pDecoder != nullptr){
  77 + return m_pDecoder->getResolution(width, height);
  78 + }
  79 + return false;
  80 +}
  81 +
  82 +bool NvDecoderApi::isSurport(FFDecConfig& cfg){
  83 + if(m_pDecoder != nullptr){
  84 + return m_pDecoder->isSurport(cfg);
  85 + }
  86 + return false;
  87 +}
  88 +
  89 +float NvDecoderApi::fps(){
  90 + if(m_pDecoder != nullptr){
  91 + return m_pDecoder->fps();
  92 + }
  93 + return 0.0;
  94 +}
  95 +
  96 +int NvDecoderApi::getCachedQueueLength(){
  97 + if(m_pDecoder != nullptr){
  98 + return m_pDecoder->getCachedQueueLength();
  99 + }
  100 + return 0;
  101 +}
  102 +
  103 +void NvDecoderApi::setName(string nm){
  104 + if(m_pDecoder != nullptr){
  105 + return m_pDecoder->setName(nm);
  106 + }
  107 +}
  108 +
  109 +string NvDecoderApi::getName(){
  110 + if(m_pDecoder != nullptr){
  111 + return m_pDecoder->getName();
  112 + }
  113 + return nullptr;
  114 +}
  115 +
  116 +FFImgInfo* NvDecoderApi::snapshot(){
  117 + if(m_pDecoder != nullptr){
  118 + return m_pDecoder->snapshot();
  119 + }
  120 + return nullptr;
  121 +}
  122 +
  123 +void NvDecoderApi::setPostDecArg(const void* postDecArg){
  124 + if(m_pDecoder != nullptr){
  125 + return m_pDecoder->setPostDecArg(postDecArg);
  126 + }
  127 +}
  128 +
  129 +void NvDecoderApi::setFinishedDecArg(const void* finishedDecArg){
  130 + if(m_pDecoder != nullptr){
  131 + return m_pDecoder->setFinishedDecArg(finishedDecArg);
  132 + }
  133 +}
0 134 \ No newline at end of file
... ...
src/nvdec/NvDecoderApi.h 0 → 100644
  1 +#include<string>
  2 +#include <pthread.h>
  3 +
  4 +#include "common_header.h"
  5 +#include "../interface/AbstractDecoder.h"
  6 +
  7 +using namespace std;
  8 +
  9 +class FFNvDecoder;
  10 +
  11 +class NvDecoderApi : public AbstractDecoder{
  12 +public:
  13 + NvDecoderApi();
  14 + ~NvDecoderApi();
  15 + bool init(FFDecConfig& cfg);
  16 + void close();
  17 + bool start();
  18 + void pause();
  19 + void resume();
  20 +
  21 + void setDecKeyframe(bool bKeyframe);
  22 +
  23 + bool isRunning();
  24 + bool isFinished();
  25 + bool isPausing();
  26 + bool getResolution( int &width, int &height );
  27 +
  28 + bool isSurport(FFDecConfig& cfg);
  29 +
  30 + int getCachedQueueLength();
  31 +
  32 + float fps();
  33 +
  34 + FFImgInfo* snapshot();
  35 +
  36 + DECODER_TYPE getDecoderType(){ return DECODER_TYPE_DVPP; }
  37 + void setName(string nm);
  38 + string getName();
  39 +
  40 + void setPostDecArg(const void* postDecArg);
  41 + void setFinishedDecArg(const void* finishedDecArg);
  42 +private:
  43 + FFNvDecoder* m_pDecoder;
  44 +};
0 45 \ No newline at end of file
... ...
src/NvJpegEncoder.cpp renamed to src/nvdec/NvJpegEncoder.cpp
src/NvJpegEncoder.h renamed to src/nvdec/NvJpegEncoder.h
src/PartMemCopy.cu renamed to src/nvdec/PartMemCopy.cu
src/RGB2YUV.cu renamed to src/nvdec/RGB2YUV.cu
src/ResizeImage.cu renamed to src/nvdec/ResizeImage.cu
src/nvdec/common_header.h 0 → 100644
  1 +#ifndef _COMMON_HEADER_H_
  2 +#define _COMMON_HEADER_H_
  3 +
  4 +
  5 +#include "../interface/logger.hpp"
  6 +#include "../interface/utiltools.hpp"
  7 +#include "../interface/interface_headers.h"
  8 +
  9 +#endif
0 10 \ No newline at end of file
... ...
src/cuda_kernels.h renamed to src/nvdec/cuda_kernels.h
src/define.hpp renamed to src/nvdec/define.hpp
... ... @@ -2,12 +2,10 @@
2 2  
3 3 #include <string>
4 4  
5   -#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
6   -
7 5  
8 6 #define CHECK_CUDA(call) \
9 7 {\
10 8 const cudaError_t error_code = call;\
11 9 if (cudaSuccess != error_code)\
12 10 LOG_ERROR("CUDA error, code: {} reason: {}", error_code, cudaGetErrorString(error_code));\
13   -}
14 11 \ No newline at end of file
  12 +}
... ...
src/jpegNPP.cpp-1 renamed to src/nvdec/jpegNPP.cpp-1