Commit 63e6f7bc581e7aa20757a0da8490155ef38032e6

Authored by Hu Chunming
1 parent 92989af0

完成dvpp。但是nv和gb28181的代码弄乱了,需要重构代码

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