Commit a25d4e5da5104ed8624819b5ca80da83f4741d31
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
.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 "C" { |
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& 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
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& 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
src/DrawImageOnGPU.cu renamed to src/nvdec/DrawImageOnGPU.cu
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
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
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
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