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,31 +2,13 @@ | ||
2 | "version": "0.2.0", | 2 | "version": "0.2.0", |
3 | "configurations": [ | 3 | "configurations": [ |
4 | { | 4 | { |
5 | - "name": "(gdb) Launch", | 5 | + "name": "dvpp", |
6 | "type": "cppdbg", | 6 | "type": "cppdbg", |
7 | "request": "launch", | 7 | "request": "launch", |
8 | "program": "${workspaceFolder}/bin/lib/test", | 8 | "program": "${workspaceFolder}/bin/lib/test", |
9 | "args": ["rtsp://192.168.10.4:8554/street","3", "30012"], | 9 | "args": ["rtsp://192.168.10.4:8554/street","3", "30012"], |
10 | "stopAtEntry": false, | 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 | "environment": [], | 12 | "environment": [], |
31 | "externalConsole": false, | 13 | "externalConsole": false, |
32 | "MIMode": "gdb", | 14 | "MIMode": "gdb", |
@@ -38,11 +20,11 @@ | @@ -38,11 +20,11 @@ | ||
38 | } | 20 | } |
39 | ] | 21 | ] |
40 | },{ | 22 | },{ |
41 | - "name": "jrtp", | 23 | + "name": "nvdec", |
42 | "type": "cppdbg", | 24 | "type": "cppdbg", |
43 | "request": "launch", | 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 | "stopAtEntry": false, | 28 | "stopAtEntry": false, |
47 | "cwd": "${workspaceFolder}/bin/lib", | 29 | "cwd": "${workspaceFolder}/bin/lib", |
48 | "environment": [], | 30 | "environment": [], |
.vscode/settings.json
@@ -62,6 +62,14 @@ | @@ -62,6 +62,14 @@ | ||
62 | "cfenv": "cpp", | 62 | "cfenv": "cpp", |
63 | "cinttypes": "cpp", | 63 | "cinttypes": "cpp", |
64 | "__nullptr": "cpp", | 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 | \ No newline at end of file | 76 | \ No newline at end of file |
README.md
1 | -#### ffmpeg编译配置 | 1 | +#### 基于CUDA的ffmpeg编译配置 |
2 | 1. 安装cuda | 2 | 1. 安装cuda |
3 | 2. 安装 nv-codec-headers | 3 | 2. 安装 nv-codec-headers |
4 | 支持 cuvid 需要安装 nv-codec-headers, 进入 nv-codec-headers 文件夹后以sudo权限make && make install即可 | 4 | 支持 cuvid 需要安装 nv-codec-headers, 进入 nv-codec-headers 文件夹后以sudo权限make && make install即可 |
@@ -11,5 +11,10 @@ | @@ -11,5 +11,10 @@ | ||
11 | --enable-debug --extra-cflags=-g --extra-ldflags=-g --disable-optimizations --disable-stripping | 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 | #### SDK说明 | 19 | #### SDK说明 |
15 | 1. 对外接口主要是 FFNvDecoderManager 类,可支持多个解码器;也可直接使用 FFNvDecoder ,但是不建议,FFNvDecoderManager已经封装了 FFNvDecoder 的接口 | 20 | 1. 对外接口主要是 FFNvDecoderManager 类,可支持多个解码器;也可直接使用 FFNvDecoder ,但是不建议,FFNvDecoderManager已经封装了 FFNvDecoder 的接口 |
16 | \ No newline at end of file | 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 | THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty | 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 | SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release | 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 | INCLUDE= -I $(DEPEND_DIR)/include \ | 23 | INCLUDE= -I $(DEPEND_DIR)/include \ |
23 | -I $(CUDA_ROOT)/include \ | 24 | -I $(CUDA_ROOT)/include \ |
@@ -37,34 +38,40 @@ LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilte | @@ -37,34 +38,40 @@ LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilte | ||
37 | -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \ | 38 | -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \ |
38 | -L $(CURL_ROOT)/lib -l:libcurl.a \ | 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 | clean: | 76 | clean: |
70 | - rm -f *.o $(TARGET) | ||
71 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | #include <iostream> | 1 | #include <iostream> |
3 | - | ||
4 | -#include "cuda_kernels.h" | ||
5 | - | ||
6 | -#include "NvJpegEncoder.h" | ||
7 | - | ||
8 | #include <pthread.h> | 2 | #include <pthread.h> |
9 | #include <thread> | 3 | #include <thread> |
10 | - | ||
11 | #include <chrono> | 4 | #include <chrono> |
12 | - | ||
13 | #include <unistd.h> | 5 | #include <unistd.h> |
14 | 6 | ||
15 | #include "FFSaveImg.h" | 7 | #include "FFSaveImg.h" |
@@ -23,7 +15,8 @@ | @@ -23,7 +15,8 @@ | ||
23 | #include "arpa/inet.h" | 15 | #include "arpa/inet.h" |
24 | #endif | 16 | #endif |
25 | 17 | ||
26 | -#include "utiltools.hpp" | 18 | +#include "../interface/FFNvDecoderManager.h" |
19 | +#include "../interface/utiltools.hpp" | ||
27 | 20 | ||
28 | #include "curl/curl.h" | 21 | #include "curl/curl.h" |
29 | 22 | ||
@@ -89,75 +82,11 @@ unsigned char *pHwRgb[2] = {nullptr, nullptr}; | @@ -89,75 +82,11 @@ unsigned char *pHwRgb[2] = {nullptr, nullptr}; | ||
89 | int sum1 = 0; | 82 | int sum1 = 0; |
90 | int sum2 = 0; | 83 | int sum2 = 0; |
91 | 84 | ||
92 | -cudaStream_t stream[2]; | ||
93 | 85 | ||
94 | string data_home = "/mnt/data/cmhu/tmp/"; | 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 | static long get_cur_time_ms() { | 91 | static long get_cur_time_ms() { |
163 | chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | 92 | chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro |
@@ -168,87 +97,15 @@ static long get_cur_time_ms() { | @@ -168,87 +97,15 @@ static long get_cur_time_ms() { | ||
168 | /** | 97 | /** |
169 | * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况 | 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 | AbstractDecoder* decoder = (AbstractDecoder*)userPtr; | 101 | AbstractDecoder* decoder = (AbstractDecoder*)userPtr; |
191 | if (decoder!= nullptr) | 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,9 +119,8 @@ int count_std = 100; | ||
262 | static int sum = 0; | 119 | static int sum = 0; |
263 | unsigned char *pHwData = nullptr; | 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 | AbstractDecoder* decoder = (AbstractDecoder*)userPtr; | 125 | AbstractDecoder* decoder = (AbstractDecoder*)userPtr; |
270 | if (decoder!= nullptr) | 126 | if (decoder!= nullptr) |
@@ -286,32 +142,12 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ | @@ -286,32 +142,12 @@ void postDecoded0(const void * userPtr, AVFrame * gpuFrame){ | ||
286 | // long time_using = end_time - start_time; | 142 | // long time_using = end_time - start_time; |
287 | // double time_per_frame = double(time_using)/count_std ; | 143 | // double time_per_frame = double(time_using)/count_std ; |
288 | // cout << count_std << "帧用时:" << time_using << "ms 每帧用时:" << time_per_frame << "ms" << endl; | 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 | // cout << gpuFrame->pts << endl; | 146 | // cout << gpuFrame->pts << endl; |
291 | 147 | ||
292 | count_flag = false; | 148 | count_flag = false; |
293 | } | 149 | } |
294 | // cout << "帧数:" << sum << endl; | 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,7 +350,9 @@ bool decode_request_stream_cbk(const char* deviceId){ | ||
514 | // string test_uri = "/home/cmhu/data/output_1920x1080.mp4"; | 350 | // string test_uri = "/home/cmhu/data/output_1920x1080.mp4"; |
515 | // string test_uri = "rtsp://176.10.0.2:8554/stream"; | 351 | // string test_uri = "rtsp://176.10.0.2:8554/stream"; |
516 | // string test_uri = "/mnt/f/fiss/test_data/h265.mp4"; | 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 | void createDecode(int index, const char* gpu_id){ | 357 | void createDecode(int index, const char* gpu_id){ |
520 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); | 358 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
@@ -575,6 +413,29 @@ void createGB28181Decode(char* devid, char* gpu_id, int port){ | @@ -575,6 +413,29 @@ void createGB28181Decode(char* devid, char* gpu_id, int port){ | ||
575 | pDecManager->startDecodeByName(config.name); | 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 | void logFF(void *, int level, const char *fmt, va_list ap) | 439 | void logFF(void *, int level, const char *fmt, va_list ap) |
579 | { | 440 | { |
580 | vfprintf(stdout, fmt, ap); | 441 | vfprintf(stdout, fmt, ap); |
@@ -583,7 +444,7 @@ void logFF(void *, int level, const char *fmt, va_list ap) | @@ -583,7 +444,7 @@ void logFF(void *, int level, const char *fmt, va_list ap) | ||
583 | 444 | ||
584 | int main(int argc, char* argv[]){ | 445 | int main(int argc, char* argv[]){ |
585 | 446 | ||
586 | - test_uri = argv[1]; | 447 | + // test_uri = argv[1]; |
587 | char* gpuid = argv[2]; | 448 | char* gpuid = argv[2]; |
588 | int port = atoi(argv[3]); | 449 | int port = atoi(argv[3]); |
589 | char* devId = argv[4]; | 450 | char* devId = argv[4]; |
@@ -591,7 +452,7 @@ int main(int argc, char* argv[]){ | @@ -591,7 +452,7 @@ int main(int argc, char* argv[]){ | ||
591 | 452 | ||
592 | // av_log_set_callback(&logFF); | 453 | // av_log_set_callback(&logFF); |
593 | 454 | ||
594 | - CheckCUDAProperty(atoi(gpuid)); | 455 | + // CheckCUDAProperty(atoi(gpuid)); |
595 | 456 | ||
596 | pthread_t m_decode_thread; | 457 | pthread_t m_decode_thread; |
597 | pthread_create(&m_decode_thread,0, | 458 | pthread_create(&m_decode_thread,0, |
@@ -644,6 +505,11 @@ int main(int argc, char* argv[]){ | @@ -644,6 +505,11 @@ int main(int argc, char* argv[]){ | ||
644 | createGB28181Decode(devId, gpuid, port); | 505 | createGB28181Decode(devId, gpuid, port); |
645 | i++; | 506 | i++; |
646 | break; | 507 | break; |
508 | + case 'd': | ||
509 | + case 'D': | ||
510 | + createDvppDecoder(i, gpuid, 0); | ||
511 | + i++; | ||
512 | + break; | ||
647 | case 'r': | 513 | case 'r': |
648 | case 'R': | 514 | case 'R': |
649 | pDecManager->resumeDecoder("dec0"); | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 34 | \ No newline at end of file |
src/gb28181/FFGB28181Decoder.cpp
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | #include <iostream> | 2 | #include <iostream> |
3 | #include "FFGB28181Decoder.h" | 3 | #include "FFGB28181Decoder.h" |
4 | 4 | ||
5 | -#include "../FFCuContextManager.h" | 5 | + |
6 | 6 | ||
7 | extern "C" { | 7 | extern "C" { |
8 | #include "libavutil/avstring.h" | 8 | #include "libavutil/avstring.h" |
@@ -17,6 +17,10 @@ extern "C" { | @@ -17,6 +17,10 @@ extern "C" { | ||
17 | 17 | ||
18 | #include "common_header.h" | 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 | #define ECLOSED 0 | 24 | #define ECLOSED 0 |
21 | #define ECLOSING 1 | 25 | #define ECLOSING 1 |
22 | #define ERUNNING 2 | 26 | #define ERUNNING 2 |
@@ -300,7 +304,7 @@ void FFGB28181Decoder::post_decode_thread(){ | @@ -300,7 +304,7 @@ void FFGB28181Decoder::post_decode_thread(){ | ||
300 | m_queue_mutex.unlock(); | 304 | m_queue_mutex.unlock(); |
301 | // 跳帧 | 305 | // 跳帧 |
302 | if (m_frameSkip == 1 || index % m_frameSkip == 0){ | 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 | av_frame_free(&gpuFrame); | 310 | av_frame_free(&gpuFrame); |
@@ -325,6 +329,14 @@ void FFGB28181Decoder::stream_end_callback() | @@ -325,6 +329,14 @@ void FFGB28181Decoder::stream_end_callback() | ||
325 | return; | 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 | void FFGB28181Decoder::pause() { | 340 | void FFGB28181Decoder::pause() { |
329 | m_status = EPAUSE; | 341 | m_status = EPAUSE; |
330 | LOG_INFO("pause --{}", m_dec_name); | 342 | LOG_INFO("pause --{}", m_dec_name); |
@@ -373,4 +385,120 @@ bool FFGB28181Decoder::isSurport(FFDecConfig& cfg){ | @@ -373,4 +385,120 @@ bool FFGB28181Decoder::isSurport(FFDecConfig& cfg){ | ||
373 | 385 | ||
374 | int FFGB28181Decoder::getCachedQueueLength(){ | 386 | int FFGB28181Decoder::getCachedQueueLength(){ |
375 | return m_rtpPtr->GetPsFrameListSize(); | 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 | \ No newline at end of file | 505 | \ No newline at end of file |
src/gb28181/FFGB28181Decoder.h
@@ -3,7 +3,8 @@ | @@ -3,7 +3,8 @@ | ||
3 | 3 | ||
4 | #include "RTPReceiver.h" | 4 | #include "RTPReceiver.h" |
5 | 5 | ||
6 | -#include "../AbstractDecoder.h" | 6 | +#include "common_header.h" |
7 | +#include "../interface/AbstractDecoder.h" | ||
7 | 8 | ||
8 | #include <atomic> | 9 | #include <atomic> |
9 | #include <mutex> | 10 | #include <mutex> |
@@ -14,6 +15,7 @@ struct AVCodec; | @@ -14,6 +15,7 @@ struct AVCodec; | ||
14 | struct AVFrame; | 15 | struct AVFrame; |
15 | struct AVPacket; | 16 | struct AVPacket; |
16 | struct SwsContext; | 17 | struct SwsContext; |
18 | +struct AVDictionary; | ||
17 | 19 | ||
18 | using namespace std; | 20 | using namespace std; |
19 | 21 | ||
@@ -44,12 +46,31 @@ public: | @@ -44,12 +46,31 @@ public: | ||
44 | 46 | ||
45 | DECODER_TYPE getDecoderType(){ return DECODER_TYPE_GB28181; } | 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 | public: | 62 | public: |
48 | void stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts); | 63 | void stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts); |
49 | void stream_end_callback(); | 64 | void stream_end_callback(); |
50 | void post_decode_thread(); | 65 | void post_decode_thread(); |
51 | 66 | ||
52 | private: | 67 | private: |
68 | + DeviceRgbMemory* convert2bgr(AVFrame * gpuFrame); | ||
69 | + | ||
70 | +private: | ||
71 | + string m_dec_name; | ||
72 | + FFDecConfig m_cfg; | ||
73 | + | ||
53 | AVCodecContext* m_pAVCodecCtx {}; | 74 | AVCodecContext* m_pAVCodecCtx {}; |
54 | const AVCodec* m_pAVCodec {}; | 75 | const AVCodec* m_pAVCodec {}; |
55 | 76 | ||
@@ -74,6 +95,17 @@ private: | @@ -74,6 +95,17 @@ private: | ||
74 | AVDictionary *gpu_options = nullptr; | 95 | AVDictionary *gpu_options = nullptr; |
75 | 96 | ||
76 | pthread_t m_post_decode_thread; | 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 | #endif // _GB28181_DECODER_H_ | 111 | #endif // _GB28181_DECODER_H_ |
src/gb28181/Makefile
0 → 100644
1 | +# 各项目录 | ||
2 | +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib | ||
3 | +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep | ||
4 | +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj | ||
5 | +SRC_DIR:=$(TOP_DIR)/$(MODULE) | ||
6 | + | ||
7 | +# 源文件以及中间目标文件和依赖文件 | ||
8 | +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp)) | ||
9 | +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS))) | ||
10 | +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS))) | ||
11 | + | ||
12 | +# 自动生成头文件依赖选项 | ||
13 | +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d | ||
14 | + | ||
15 | +JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export | ||
16 | + | ||
17 | +INCLUDE= -I $(TOP_DIR)/common/inc \ | ||
18 | + -I $(TOP_DIR)/common/UtilNPP \ | ||
19 | + -I $(TOP_DIR)/ \ | ||
20 | + -I $(CUDA_ROOT)/include \ | ||
21 | + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \ | ||
22 | + -I $(JRTP_ROOT)/jthread/include/jthread | ||
23 | + | ||
24 | +LIBSPATH= -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \ | ||
25 | + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \ | ||
26 | + -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \ | ||
27 | + | ||
28 | + | ||
29 | +CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(INCS) $(LIBS) $(LIBSPATH) $(MACROS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl -Wwrite-strings | ||
30 | + | ||
31 | +# 最终目标文件 | ||
32 | +TARGET:=$(LIB_DIR)/$(MODULE).a | ||
33 | + | ||
34 | +# 默认最终目标 | ||
35 | +.PHONY:all | ||
36 | +all:$(TARGET) | ||
37 | + | ||
38 | +# 生成最终目标 | ||
39 | +$(TARGET):$(OBJS) | $(LIB_DIR) | ||
40 | + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m" | ||
41 | + @echo -e "ar -rc $@ $^" | ||
42 | + @ar -rc $@ $^ | ||
43 | + | ||
44 | +# 若没有lib目录则自动生成 | ||
45 | +$(LIB_DIR): | ||
46 | + @mkdir -p $@ | ||
47 | + | ||
48 | +# 生成中间目标文件 | ||
49 | +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR) | ||
50 | + @echo -e "\e[33m""Building object $@""\e[0m" | ||
51 | + @echo -e "$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<" | ||
52 | + @$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $< | ||
53 | + | ||
54 | +# 若没有obj目录则自动生成 | ||
55 | +$(OBJ_DIR): | ||
56 | + @mkdir -p $@ | ||
57 | + | ||
58 | +# 若没有.dep目录则自动生成 | ||
59 | +$(DEP_DIR): | ||
60 | + @mkdir -p $@ | ||
61 | + | ||
62 | +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错 | ||
63 | +$(DEPS): | ||
64 | + | ||
65 | +# 引入中间目标文件头文件依赖关系 | ||
66 | +include $(wildcard $(DEPS)) | ||
67 | + | ||
68 | +# 直接删除组件build目录 | ||
69 | +.PHONY:clean | ||
70 | +clean: | ||
71 | + @rm -rf $(BUILD_DIR)/$(MODULE) |
src/gb28181/common_header.h
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | #define _COMMON_HEADER_H_ | 2 | #define _COMMON_HEADER_H_ |
3 | 3 | ||
4 | 4 | ||
5 | -#include "../logger.hpp" | ||
6 | -#include "../utiltools.hpp" | 5 | +#include "../interface/logger.hpp" |
6 | +#include "../interface/utiltools.hpp" | ||
7 | 7 | ||
8 | #endif | 8 | #endif |
9 | \ No newline at end of file | 9 | \ No newline at end of file |
src/interface/AbstractDecoder.cpp
0 → 100644
1 | +#include "AbstractDecoder.h" | ||
2 | + | ||
3 | +#include "logger.hpp" | ||
4 | +#include "utiltools.hpp" | ||
5 | + | ||
6 | + | ||
7 | +bool AbstractDecoder::isSnapTime(){ | ||
8 | + if(m_snap_time_interval <= 0){ | ||
9 | + return false; | ||
10 | + } | ||
11 | + long cur_time = UtilTools::get_cur_time_ms(); | ||
12 | + if(cur_time - m_last_snap_time > m_snap_time_interval){ | ||
13 | + return true; | ||
14 | + } | ||
15 | + return false; | ||
16 | +} | ||
17 | + | ||
18 | +void AbstractDecoder::updateLastSnapTime(){ | ||
19 | + m_last_snap_time = UtilTools::get_cur_time_ms(); | ||
20 | +} | ||
21 | + | ||
22 | +void AbstractDecoder::setSnapTimeInterval(long interval){ | ||
23 | + m_snap_time_interval = interval; | ||
24 | + m_last_snap_time = UtilTools::get_cur_time_ms(); | ||
25 | +} | ||
0 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | #include<string> | 4 | #include<string> |
2 | 5 | ||
3 | -#include "cuda_kernels.h" | ||
4 | -#include "define.hpp" | ||
5 | #include "utiltools.hpp" | 6 | #include "utiltools.hpp" |
6 | 7 | ||
7 | using namespace std; | 8 | using namespace std; |
8 | 9 | ||
9 | -class GpuRgbMemory{ | 10 | +class DeviceRgbMemory{ |
10 | 11 | ||
11 | public: | 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 | channel = _channel; | 14 | channel = _channel; |
14 | width = _width; | 15 | width = _width; |
15 | height = _height; | 16 | height = _height; |
16 | - size = channel * width * height; | 17 | + data_size = channel * width * height; |
17 | isused = _isused; | 18 | isused = _isused; |
18 | id = _id; | 19 | id = _id; |
19 | - gpuid = _gpuid; | 20 | + device_id = _dev_id; |
21 | + key_frame = _key_frame; | ||
20 | timestamp = UtilTools::get_cur_time_ms(); | 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 | int getSize() { | 27 | int getSize() { |
35 | - return size; | 28 | + return data_size; |
36 | } | 29 | } |
37 | 30 | ||
38 | bool isIsused() { | 31 | bool isIsused() { |
@@ -49,8 +42,8 @@ public: | @@ -49,8 +42,8 @@ public: | ||
49 | return id; | 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 | unsigned char* getMem(){ | 49 | unsigned char* getMem(){ |
@@ -73,14 +66,21 @@ public: | @@ -73,14 +66,21 @@ public: | ||
73 | return channel; | 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 | bool isused; | 75 | bool isused; |
79 | string id; | 76 | string id; |
80 | - string gpuid; | 77 | + string device_id; |
81 | unsigned char * pHwRgb{nullptr}; | 78 | unsigned char * pHwRgb{nullptr}; |
82 | long long timestamp; | 79 | long long timestamp; |
83 | int width{0}; | 80 | int width{0}; |
84 | int height{0}; | 81 | int height{0}; |
85 | int channel{3}; | 82 | int channel{3}; |
86 | -}; | ||
87 | \ No newline at end of file | 83 | \ No newline at end of file |
84 | + bool key_frame; | ||
85 | +}; | ||
86 | + | ||
87 | +#endif | ||
88 | \ No newline at end of file | 88 | \ No newline at end of file |
src/FFNvDecoderManager.cpp renamed to src/interface/FFNvDecoderManager.cpp
1 | #include "FFNvDecoderManager.h" | 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 | #include "logger.hpp" | 12 | #include "logger.hpp" |
7 | 13 | ||
@@ -25,22 +31,31 @@ AbstractDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){ | @@ -25,22 +31,31 @@ AbstractDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){ | ||
25 | } | 31 | } |
26 | 32 | ||
27 | AbstractDecoder* dec = nullptr; | 33 | AbstractDecoder* dec = nullptr; |
34 | +#ifdef USE_NVDEC | ||
28 | if(DECODER_TYPE_FFMPEG == config.dec_type){ | 35 | if(DECODER_TYPE_FFMPEG == config.dec_type){ |
29 | dec = new FFNvDecoder(); | 36 | dec = new FFNvDecoder(); |
30 | - }else if(DECODER_TYPE_GB28181 == config.dec_type){ | 37 | + } |
38 | + | ||
39 | + if(DECODER_TYPE_GB28181 == config.dec_type){ | ||
31 | dec = new FFGB28181Decoder(); | 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 | if (dec == nullptr){ | 50 | if (dec == nullptr){ |
35 | LOG_ERROR("没有指定解码器类型"); | 51 | LOG_ERROR("没有指定解码器类型"); |
36 | return nullptr; | 52 | return nullptr; |
37 | } | 53 | } |
38 | 54 | ||
55 | + config.cfg.dec_name = config.name; | ||
39 | bool bRet= dec->init(config.cfg); | 56 | bool bRet= dec->init(config.cfg); |
40 | if (bRet) | 57 | if (bRet) |
41 | { | 58 | { |
42 | - dec->setName(config.name) ; | ||
43 | - dec->setSnapTimeInterval(config.snap_time_interval); | ||
44 | decoderMap[config.name] = dec; | 59 | decoderMap[config.name] = dec; |
45 | 60 | ||
46 | LOG_INFO("[{}][{}]- 解码器初始化成功",config.name, config.cfg.uri); | 61 | LOG_INFO("[{}][{}]- 解码器初始化成功",config.name, config.cfg.uri); |
@@ -68,7 +83,7 @@ bool FFNvDecoderManager::setPostDecArg(const string name, const void * userPtr) | @@ -68,7 +83,7 @@ bool FFNvDecoderManager::setPostDecArg(const string name, const void * userPtr) | ||
68 | auto dec = decoderMap.find(name); | 83 | auto dec = decoderMap.find(name); |
69 | if (dec != decoderMap.end()) | 84 | if (dec != decoderMap.end()) |
70 | { | 85 | { |
71 | - dec->second->m_postDecArg = userPtr; | 86 | + dec->second->setPostDecArg(userPtr); |
72 | return true; | 87 | return true; |
73 | } | 88 | } |
74 | 89 | ||
@@ -89,7 +104,7 @@ bool FFNvDecoderManager::setFinishedDecArg(const string name, const void * userP | @@ -89,7 +104,7 @@ bool FFNvDecoderManager::setFinishedDecArg(const string name, const void * userP | ||
89 | auto dec = decoderMap.find(name); | 104 | auto dec = decoderMap.find(name); |
90 | if (dec != decoderMap.end()) | 105 | if (dec != decoderMap.end()) |
91 | { | 106 | { |
92 | - dec->second->m_finishedDecArg = userPtr; | 107 | + dec->second->setFinishedDecArg(userPtr); |
93 | return true; | 108 | return true; |
94 | } | 109 | } |
95 | 110 | ||
@@ -273,11 +288,21 @@ bool FFNvDecoderManager::isSurport(MgrDecConfig& config) | @@ -273,11 +288,21 @@ bool FFNvDecoderManager::isSurport(MgrDecConfig& config) | ||
273 | } | 288 | } |
274 | 289 | ||
275 | AbstractDecoder* dec = nullptr; | 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 | dec = new FFNvDecoder(); | 293 | dec = new FFNvDecoder(); |
278 | - }else if(config.dec_type = DECODER_TYPE_GB28181){ | 294 | + } |
295 | + | ||
296 | + if(DECODER_TYPE_GB28181 == config.dec_type){ | ||
279 | dec = new FFGB28181Decoder(); | 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 | if (dec == nullptr){ | 307 | if (dec == nullptr){ |
283 | LOG_ERROR("没有指定解码器类型"); | 308 | LOG_ERROR("没有指定解码器类型"); |
@@ -420,142 +445,10 @@ int FFNvDecoderManager::getCachedQueueLength(const string name){ | @@ -420,142 +445,10 @@ int FFNvDecoderManager::getCachedQueueLength(const string name){ | ||
420 | return -1; | 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 | void FFNvDecoderManager::releaseFFImgInfo(FFImgInfo* info){ | 448 | void FFNvDecoderManager::releaseFFImgInfo(FFImgInfo* info){ |
556 | if(nullptr != info){ | 449 | if(nullptr != info){ |
557 | if(info->pData != nullptr){ | 450 | if(info->pData != nullptr){ |
558 | - av_free(info->pData); | 451 | + free(info->pData); |
559 | info->pData = nullptr; | 452 | info->pData = nullptr; |
560 | } | 453 | } |
561 | delete info; | 454 | delete info; |
src/FFNvDecoderManager.h renamed to src/interface/FFNvDecoderManager.h
@@ -15,6 +15,8 @@ struct MgrDecConfig | @@ -15,6 +15,8 @@ struct MgrDecConfig | ||
15 | long snap_time_interval; // 定时抓拍时间间隔 | 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,15 +238,6 @@ public: | ||
236 | int getCachedQueueLength(const string name); | 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 | * 接口:releaseFFImgInfo | 241 | * 接口:releaseFFImgInfo |
249 | * 功能:释放视频快照信息 | 242 | * 功能:释放视频快照信息 |
250 | * 参数:FFImgInfo* info 视频快照信息 | 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 | #include <queue> | 6 | #include <queue> |
19 | #include <mutex> | 7 | #include <mutex> |
20 | 8 | ||
9 | +#include "DeviceRgbMemory.hpp" | ||
10 | + | ||
21 | using namespace std; | 11 | using namespace std; |
22 | 12 | ||
23 | /************************************************** | 13 | /************************************************** |
@@ -31,7 +21,7 @@ using namespace std; | @@ -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 | typedef void(*DECODE_FINISHED_CALLBACK)(const void* userPtr); | 26 | typedef void(*DECODE_FINISHED_CALLBACK)(const void* userPtr); |
37 | 27 | ||
@@ -44,6 +34,7 @@ struct FFDecConfig{ | @@ -44,6 +34,7 @@ struct FFDecConfig{ | ||
44 | string gpuid; // gpu id | 34 | string gpuid; // gpu id |
45 | bool force_tcp{true}; // 是否指定使用tcp连接 | 35 | bool force_tcp{true}; // 是否指定使用tcp连接 |
46 | int skip_frame{1}; // 跳帧数 | 36 | int skip_frame{1}; // 跳帧数 |
37 | + string dec_name; | ||
47 | 38 | ||
48 | int port; // gb28181接收数据的端口号 | 39 | int port; // gb28181接收数据的端口号 |
49 | DECODE_REQUEST_STREAM_CALLBACK request_stream_cbk; // gb28181请求流 | 40 | DECODE_REQUEST_STREAM_CALLBACK request_stream_cbk; // gb28181请求流 |
@@ -51,7 +42,8 @@ struct FFDecConfig{ | @@ -51,7 +42,8 @@ struct FFDecConfig{ | ||
51 | 42 | ||
52 | enum DECODER_TYPE{ | 43 | enum DECODER_TYPE{ |
53 | DECODER_TYPE_GB28181, | 44 | DECODER_TYPE_GB28181, |
54 | - DECODER_TYPE_FFMPEG | 45 | + DECODER_TYPE_FFMPEG, |
46 | + DECODER_TYPE_DVPP | ||
55 | }; | 47 | }; |
56 | 48 | ||
57 | struct FFImgInfo{ | 49 | struct FFImgInfo{ |
@@ -59,70 +51,9 @@ struct FFImgInfo{ | @@ -59,70 +51,9 @@ struct FFImgInfo{ | ||
59 | int width; | 51 | int width; |
60 | int height; | 52 | int height; |
61 | unsigned char * pData; | 53 | unsigned char * pData; |
54 | + int data_type; // 默认0=rgb, 1=nv12 | ||
62 | long timestamp; | 55 | long timestamp; |
63 | long index; | 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 | \ No newline at end of file | 59 | \ No newline at end of file |
60 | +#endif | ||
130 | \ No newline at end of file | 61 | \ No newline at end of file |
src/logger.hpp renamed to src/interface/logger.hpp
@@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
8 | 8 | ||
9 | #pragma once | 9 | #pragma once |
10 | 10 | ||
11 | -#include "define.hpp" | 11 | +// #include "define.hpp" |
12 | #include <spdlog/spdlog.h> | 12 | #include <spdlog/spdlog.h> |
13 | #include <spdlog/common.h> | 13 | #include <spdlog/common.h> |
14 | #include <spdlog/details/file_helper.h> | 14 | #include <spdlog/details/file_helper.h> |
@@ -28,6 +28,8 @@ | @@ -28,6 +28,8 @@ | ||
28 | #include <memory> | 28 | #include <memory> |
29 | #include <vector> | 29 | #include <vector> |
30 | 30 | ||
31 | +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) | ||
32 | + | ||
31 | #define LOG_TRACE_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_TRACE(logger, __VA_ARGS__);} | 33 | #define LOG_TRACE_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_TRACE(logger, __VA_ARGS__);} |
32 | #define LOG_DEBUG_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_DEBUG(logger, __VA_ARGS__);} | 34 | #define LOG_DEBUG_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_DEBUG(logger, __VA_ARGS__);} |
33 | #define LOG_WARN_WITH_LOGGER(logger, ...) {SPDLOG_LOGGER_WARN(logger, __VA_ARGS__);} | 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 | #include "FFCuContextManager.h" | 1 | #include "FFCuContextManager.h" |
2 | 2 | ||
3 | -#include "logger.hpp" | 3 | +#include "common_header.h" |
4 | 4 | ||
5 | using namespace std; | 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 | FFCuContextManager::~FFCuContextManager() | 19 | FFCuContextManager::~FFCuContextManager() |
8 | { | 20 | { |
9 | for(auto iter = ctxMap.begin(); iter != ctxMap.end(); iter++){ | 21 | for(auto iter = ctxMap.begin(); iter != ctxMap.end(); iter++){ |
src/FFCuContextManager.h renamed to src/nvdec/FFCuContextManager.h
@@ -2,19 +2,10 @@ | @@ -2,19 +2,10 @@ | ||
2 | #include<map> | 2 | #include<map> |
3 | #include<string> | 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 | using namespace std; | 5 | using namespace std; |
17 | 6 | ||
7 | +struct AVBufferRef; | ||
8 | + | ||
18 | class FFCuContextManager{ | 9 | class FFCuContextManager{ |
19 | public: | 10 | public: |
20 | static FFCuContextManager* getInstance(){ | 11 | static FFCuContextManager* getInstance(){ |
src/FFNvDecoder.cpp renamed to src/nvdec/FFNvDecoder.cpp
@@ -8,9 +8,10 @@ | @@ -8,9 +8,10 @@ | ||
8 | 8 | ||
9 | #include "FFCuContextManager.h" | 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 | using namespace std; | 16 | using namespace std; |
16 | 17 | ||
@@ -62,6 +63,7 @@ FFNvDecoder::~FFNvDecoder() | @@ -62,6 +63,7 @@ FFNvDecoder::~FFNvDecoder() | ||
62 | bool FFNvDecoder::init(FFDecConfig& cfg) | 63 | bool FFNvDecoder::init(FFDecConfig& cfg) |
63 | { | 64 | { |
64 | m_cfg = cfg; | 65 | m_cfg = cfg; |
66 | + m_dec_name = cfg.dec_name; | ||
65 | 67 | ||
66 | fstream infile(cfg.uri); | 68 | fstream infile(cfg.uri); |
67 | if (infile.is_open()){ | 69 | if (infile.is_open()){ |
@@ -217,16 +219,6 @@ void FFNvDecoder::decode_thread() | @@ -217,16 +219,6 @@ void FFNvDecoder::decode_thread() | ||
217 | continue; | 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 | if (stream_index == pkt->stream_index){ | 222 | if (stream_index == pkt->stream_index){ |
231 | result = avcodec_send_packet(avctx, pkt); | 223 | result = avcodec_send_packet(avctx, pkt); |
232 | if (result < 0){ | 224 | if (result < 0){ |
@@ -245,6 +237,14 @@ void FFNvDecoder::decode_thread() | @@ -245,6 +237,14 @@ void FFNvDecoder::decode_thread() | ||
245 | } | 237 | } |
246 | av_packet_unref(pkt); | 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 | if(gpuFrame != nullptr){ | 248 | if(gpuFrame != nullptr){ |
249 | m_queue_mutex.lock(); | 249 | m_queue_mutex.lock(); |
250 | if(mFrameQueue.size() <= 10){ | 250 | if(mFrameQueue.size() <= 10){ |
@@ -259,6 +259,7 @@ void FFNvDecoder::decode_thread() | @@ -259,6 +259,7 @@ void FFNvDecoder::decode_thread() | ||
259 | } | 259 | } |
260 | 260 | ||
261 | m_bRunning = false; | 261 | m_bRunning = false; |
262 | + av_packet_free(&pkt); | ||
262 | 263 | ||
263 | // long end_time = UtilTools::get_cur_time_ms(); | 264 | // long end_time = UtilTools::get_cur_time_ms(); |
264 | // cout << "解码用时:" << end_time - start_time << endl; | 265 | // cout << "解码用时:" << end_time - start_time << endl; |
@@ -315,7 +316,7 @@ void FFNvDecoder::post_decode_thread(){ | @@ -315,7 +316,7 @@ void FFNvDecoder::post_decode_thread(){ | ||
315 | m_queue_mutex.unlock(); | 316 | m_queue_mutex.unlock(); |
316 | // 跳帧 | 317 | // 跳帧 |
317 | if (skip_frame == 1 || index % skip_frame == 0){ | 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 | index = 0; | 320 | index = 0; |
320 | } | 321 | } |
321 | 322 | ||
@@ -386,3 +387,127 @@ int FFNvDecoder::getCachedQueueLength(){ | @@ -386,3 +387,127 @@ int FFNvDecoder::getCachedQueueLength(){ | ||
386 | float FFNvDecoder::fps(){ | 387 | float FFNvDecoder::fps(){ |
387 | return m_fps; | 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 | \ No newline at end of file | 514 | \ No newline at end of file |
src/FFNvDecoder.h renamed to src/nvdec/FFNvDecoder.h
1 | #include<string> | 1 | #include<string> |
2 | #include <pthread.h> | 2 | #include <pthread.h> |
3 | 3 | ||
4 | -#include "AbstractDecoder.h" | ||
5 | - | ||
6 | #include <mutex> | 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 | using namespace std; | 22 | using namespace std; |
9 | 23 | ||
10 | -class FFNvDecoder : public AbstractDecoder{ | 24 | +class FFNvDecoder : public AbstractDecoder { |
11 | public: | 25 | public: |
12 | FFNvDecoder(); | 26 | FFNvDecoder(); |
13 | ~FFNvDecoder(); | 27 | ~FFNvDecoder(); |
@@ -32,6 +46,19 @@ public: | @@ -32,6 +46,19 @@ public: | ||
32 | 46 | ||
33 | DECODER_TYPE getDecoderType(){ return DECODER_TYPE_FFMPEG; } | 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 | public: | 62 | public: |
36 | AVPixelFormat getHwPixFmt(); | 63 | AVPixelFormat getHwPixFmt(); |
37 | 64 | ||
@@ -41,7 +68,12 @@ private: | @@ -41,7 +68,12 @@ private: | ||
41 | bool init(const char* uri, const char* gpuid, bool force_tcp); | 68 | bool init(const char* uri, const char* gpuid, bool force_tcp); |
42 | void decode_finished(); | 69 | void decode_finished(); |
43 | 70 | ||
71 | + DeviceRgbMemory* convert2bgr(AVFrame * gpuFrame); | ||
72 | + | ||
44 | private: | 73 | private: |
74 | + string m_dec_name; | ||
75 | + FFDecConfig m_cfg; | ||
76 | + | ||
45 | AVStream* stream; | 77 | AVStream* stream; |
46 | AVCodecContext *avctx; | 78 | AVCodecContext *avctx; |
47 | int stream_index; | 79 | int stream_index; |
@@ -59,4 +91,17 @@ private: | @@ -59,4 +91,17 @@ private: | ||
59 | bool m_bReal; // 是否实时流 | 91 | bool m_bReal; // 是否实时流 |
60 | 92 | ||
61 | float m_fps; | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 35 | \ No newline at end of file |
src/ImageSaveGPU.cpp renamed to src/nvdec/ImageSaveGPU.cpp
1 | #include "cuda_kernels.h" | 1 | #include "cuda_kernels.h" |
2 | 2 | ||
3 | -#include "logger.hpp" | 3 | +#include "common_header.h" |
4 | 4 | ||
5 | 5 | ||
6 | //int saveJPEG(const char *szOutputFile, float* d_srcRGB, int img_width, int img_height) | 6 | //int saveJPEG(const char *szOutputFile, float* d_srcRGB, int img_width, int img_height) |
src/ImageSaveGPU.h renamed to src/nvdec/ImageSaveGPU.h
src/nvdec/Makefile
0 → 100644
1 | +# 各项目录 | ||
2 | +LIB_DIR:=$(BUILD_DIR)/$(MODULE)/lib | ||
3 | +DEP_DIR:=$(BUILD_DIR)/$(MODULE)/.dep | ||
4 | +OBJ_DIR:=$(BUILD_DIR)/$(MODULE)/obj | ||
5 | +SRC_DIR:=$(TOP_DIR)/$(MODULE) | ||
6 | + | ||
7 | +# 源文件以及中间目标文件和依赖文件 | ||
8 | +SRCS:=$(notdir $(wildcard $(SRC_DIR)/*.cpp)) | ||
9 | +OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SRCS))) | ||
10 | +DEPS:=$(addprefix $(DEP_DIR)/, $(patsubst %.cpp, %.d,a $(SRCS))) | ||
11 | + | ||
12 | + | ||
13 | +NVCC = $(CUDA_ROOT)/bin/nvcc | ||
14 | + | ||
15 | +# 自动生成头文件依赖选项 | ||
16 | +DEPFLAGS=-MT $@ -MMD -MP -MF $(DEP_DIR)/$*.d | ||
17 | + | ||
18 | +DEFS = | ||
19 | + | ||
20 | +# 最终目标文件 | ||
21 | +TARGET:=$(LIB_DIR)/$(MODULE).a | ||
22 | + | ||
23 | + | ||
24 | +JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export | ||
25 | + | ||
26 | +INCLUDE= -I $(TOP_DIR)/common/inc \ | ||
27 | + -I $(TOP_DIR)/common/UtilNPP \ | ||
28 | + -I $(TOP_DIR) \ | ||
29 | + -I $(CUDA_ROOT)/include \ | ||
30 | + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \ | ||
31 | + -I $(JRTP_ROOT)/jthread/include/jthread | ||
32 | + | ||
33 | +LIBSPATH= -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \ | ||
34 | + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \ | ||
35 | + -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \ | ||
36 | + | ||
37 | +CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(LIBSPATH) $(DEFS) $(INCS) $(LIBS) $(MACROS) -lpthread -lrt -lz -fexceptions -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl -Wwrite-strings | ||
38 | + # -DUNICODE -D_UNICODE | ||
39 | + | ||
40 | +NFLAGS_LIB=-g -c -shared -Xcompiler -fPIC | ||
41 | +NFLAGS = $(NFLAGS_LIB) $(INCLUDE) $(LIBSPATH) -std=c++11 | ||
42 | + | ||
43 | +CU_SOURCES:=$(notdir $(wildcard $(SRC_DIR)/*.cu)) | ||
44 | +CU_OBJS:=$(addprefix $(OBJ_DIR)/, $(patsubst %.cu, %.o, $(CU_SOURCES))) | ||
45 | + | ||
46 | + | ||
47 | +# 默认最终目标 | ||
48 | +.PHONY:all | ||
49 | +all:$(TARGET) | ||
50 | + | ||
51 | +# 生成最终目标 | ||
52 | +$(TARGET):$(OBJS) $(CU_OBJS) | $(LIB_DIR) | ||
53 | + @echo -e "\e[32m""Linking static library $(TARGET)""\e[0m" | ||
54 | + @echo -e "ar -rc $@ $^" | ||
55 | + @ar -rc $@ $^ | ||
56 | + | ||
57 | +# 若没有lib目录则自动生成 | ||
58 | +$(LIB_DIR): | ||
59 | + @mkdir -p $@ | ||
60 | + | ||
61 | +# 生成中间目标文件 | ||
62 | +$(OBJ_DIR)/%.o:$(SRC_DIR)/%.cpp $(DEP_DIR)/%.d | $(OBJ_DIR) $(DEP_DIR) | ||
63 | + @echo -e "\e[33m""Building object $@""\e[0m" | ||
64 | + @echo "$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $<" | ||
65 | + @$(CXX) -c $(DEPFLAGS) $(CXXFLAGS) -o $@ $< | ||
66 | + | ||
67 | +$(OBJ_DIR)%.o:$(SRC_DIR)/%.cu | ||
68 | + @echo -e "\e[33m""Building object $@""\e[0m" | ||
69 | + @echo "$(NVCC) $(NFLAGS) $(INCS) $(LIBS) -o $@ $<" | ||
70 | + $(NVCC) $(NFLAGS) $(INCS) $(LIBS) -o $@ $< | ||
71 | + | ||
72 | + | ||
73 | +# 若没有obj目录则自动生成 | ||
74 | +$(OBJ_DIR): | ||
75 | + @mkdir -p $@ | ||
76 | + | ||
77 | +# 若没有.dep目录则自动生成 | ||
78 | +$(DEP_DIR): | ||
79 | + @mkdir -p $@ | ||
80 | + | ||
81 | +# 依赖文件会在生成中间文件的时候自动生成,这里只是为了防止报错 | ||
82 | +$(DEPS): | ||
83 | + | ||
84 | +# 引入中间目标文件头文件依赖关系 | ||
85 | +include $(wildcard $(DEPS)) | ||
86 | + | ||
87 | +# 直接删除组件build目录 | ||
88 | +.PHONY:clean | ||
89 | +clean: | ||
90 | + @rm -rf $(BUILD_DIR)/$(MODULE) |
src/NV12ToRGB.cu renamed to src/nvdec/NV12ToRGB.cu
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | #include "cuda_kernels.h" | 2 | #include "cuda_kernels.h" |
3 | 3 | ||
4 | #include <builtin_types.h> | 4 | #include <builtin_types.h> |
5 | -#include "common/inc/helper_cuda_drvapi.h" | 5 | +#include "helper_cuda_drvapi.h" |
6 | 6 | ||
7 | typedef unsigned char uint8; | 7 | typedef unsigned char uint8; |
8 | typedef unsigned int uint32; | 8 | typedef unsigned int uint32; |
src/nvdec/NvDecoderApi.cpp
0 → 100644
1 | +#include "NvDecoderApi.h" | ||
2 | +#include "FFNvDecoder.h" | ||
3 | + | ||
4 | +NvDecoderApi::NvDecoderApi(){ | ||
5 | + m_pDecoder = nullptr; | ||
6 | +} | ||
7 | + | ||
8 | +NvDecoderApi::~NvDecoderApi(){ | ||
9 | + if(m_pDecoder != nullptr){ | ||
10 | + delete m_pDecoder; | ||
11 | + m_pDecoder = nullptr; | ||
12 | + } | ||
13 | +} | ||
14 | + | ||
15 | +bool NvDecoderApi::init(FFDecConfig& cfg){ | ||
16 | + m_pDecoder = new FFNvDecoder(); | ||
17 | + if(m_pDecoder != nullptr){ | ||
18 | + return m_pDecoder->init(cfg); | ||
19 | + } | ||
20 | + return false; | ||
21 | +} | ||
22 | + | ||
23 | +void NvDecoderApi::close(){ | ||
24 | + if(m_pDecoder != nullptr){ | ||
25 | + return m_pDecoder->close(); | ||
26 | + } | ||
27 | +} | ||
28 | + | ||
29 | +bool NvDecoderApi::start(){ | ||
30 | + if(m_pDecoder != nullptr){ | ||
31 | + return m_pDecoder->start(); | ||
32 | + } | ||
33 | + return false; | ||
34 | +} | ||
35 | + | ||
36 | +void NvDecoderApi::pause(){ | ||
37 | + if(m_pDecoder != nullptr){ | ||
38 | + return m_pDecoder->pause(); | ||
39 | + } | ||
40 | +} | ||
41 | + | ||
42 | +void NvDecoderApi::resume(){ | ||
43 | + if(m_pDecoder != nullptr){ | ||
44 | + return m_pDecoder->resume(); | ||
45 | + } | ||
46 | +} | ||
47 | + | ||
48 | +void NvDecoderApi::setDecKeyframe(bool bKeyframe){ | ||
49 | + if(m_pDecoder != nullptr){ | ||
50 | + return m_pDecoder->setDecKeyframe(bKeyframe); | ||
51 | + } | ||
52 | +} | ||
53 | + | ||
54 | +bool NvDecoderApi::isRunning(){ | ||
55 | + if(m_pDecoder != nullptr){ | ||
56 | + return m_pDecoder->isRunning(); | ||
57 | + } | ||
58 | + return false; | ||
59 | +} | ||
60 | + | ||
61 | +bool NvDecoderApi::isFinished(){ | ||
62 | + if(m_pDecoder != nullptr){ | ||
63 | + return m_pDecoder->isFinished(); | ||
64 | + } | ||
65 | + return false; | ||
66 | +} | ||
67 | + | ||
68 | +bool NvDecoderApi::isPausing(){ | ||
69 | + if(m_pDecoder != nullptr){ | ||
70 | + return m_pDecoder->isPausing(); | ||
71 | + } | ||
72 | + return false; | ||
73 | +} | ||
74 | + | ||
75 | +bool NvDecoderApi::getResolution(int &width, int &height){ | ||
76 | + if(m_pDecoder != nullptr){ | ||
77 | + return m_pDecoder->getResolution(width, height); | ||
78 | + } | ||
79 | + return false; | ||
80 | +} | ||
81 | + | ||
82 | +bool NvDecoderApi::isSurport(FFDecConfig& cfg){ | ||
83 | + if(m_pDecoder != nullptr){ | ||
84 | + return m_pDecoder->isSurport(cfg); | ||
85 | + } | ||
86 | + return false; | ||
87 | +} | ||
88 | + | ||
89 | +float NvDecoderApi::fps(){ | ||
90 | + if(m_pDecoder != nullptr){ | ||
91 | + return m_pDecoder->fps(); | ||
92 | + } | ||
93 | + return 0.0; | ||
94 | +} | ||
95 | + | ||
96 | +int NvDecoderApi::getCachedQueueLength(){ | ||
97 | + if(m_pDecoder != nullptr){ | ||
98 | + return m_pDecoder->getCachedQueueLength(); | ||
99 | + } | ||
100 | + return 0; | ||
101 | +} | ||
102 | + | ||
103 | +void NvDecoderApi::setName(string nm){ | ||
104 | + if(m_pDecoder != nullptr){ | ||
105 | + return m_pDecoder->setName(nm); | ||
106 | + } | ||
107 | +} | ||
108 | + | ||
109 | +string NvDecoderApi::getName(){ | ||
110 | + if(m_pDecoder != nullptr){ | ||
111 | + return m_pDecoder->getName(); | ||
112 | + } | ||
113 | + return nullptr; | ||
114 | +} | ||
115 | + | ||
116 | +FFImgInfo* NvDecoderApi::snapshot(){ | ||
117 | + if(m_pDecoder != nullptr){ | ||
118 | + return m_pDecoder->snapshot(); | ||
119 | + } | ||
120 | + return nullptr; | ||
121 | +} | ||
122 | + | ||
123 | +void NvDecoderApi::setPostDecArg(const void* postDecArg){ | ||
124 | + if(m_pDecoder != nullptr){ | ||
125 | + return m_pDecoder->setPostDecArg(postDecArg); | ||
126 | + } | ||
127 | +} | ||
128 | + | ||
129 | +void NvDecoderApi::setFinishedDecArg(const void* finishedDecArg){ | ||
130 | + if(m_pDecoder != nullptr){ | ||
131 | + return m_pDecoder->setFinishedDecArg(finishedDecArg); | ||
132 | + } | ||
133 | +} | ||
0 | \ No newline at end of file | 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 | \ No newline at end of file | 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,12 +2,10 @@ | ||
2 | 2 | ||
3 | #include <string> | 3 | #include <string> |
4 | 4 | ||
5 | -#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) | ||
6 | - | ||
7 | 5 | ||
8 | #define CHECK_CUDA(call) \ | 6 | #define CHECK_CUDA(call) \ |
9 | {\ | 7 | {\ |
10 | const cudaError_t error_code = call;\ | 8 | const cudaError_t error_code = call;\ |
11 | if (cudaSuccess != error_code)\ | 9 | if (cudaSuccess != error_code)\ |
12 | LOG_ERROR("CUDA error, code: {} reason: {}", error_code, cudaGetErrorString(error_code));\ | 10 | LOG_ERROR("CUDA error, code: {} reason: {}", error_code, cudaGetErrorString(error_code));\ |
13 | -} | ||
14 | \ No newline at end of file | 11 | \ No newline at end of file |
12 | +} |
src/jpegNPP.cpp-1 renamed to src/nvdec/jpegNPP.cpp-1