Commit 7e9074f2447e74ba3787ed6c93bc0354c1514a56

Authored by Hu Chunming
1 parent d384f0e9

添加check_tool

check_tool/FFCuContextManager.cpp 0 → 100644
  1 +#include "FFCuContextManager.h"
  2 +#include <iostream>
  3 +
  4 +using namespace std;
  5 +
  6 +FFCuContextManager::~FFCuContextManager()
  7 +{
  8 + for(auto iter = ctxMap.begin(); iter != ctxMap.end(); iter++){
  9 + av_buffer_unref(&iter->second);
  10 + }
  11 + ctxMap.clear();
  12 +}
  13 +
  14 +AVBufferRef *FFCuContextManager::getCuCtx(string gpuid)
  15 +{
  16 + AVBufferRef *hw_device_ctx = ctxMap[gpuid];
  17 + if (nullptr == hw_device_ctx)
  18 + {
  19 + // 初始化硬件解码器
  20 + if (av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, gpuid.c_str(), nullptr, 0) < 0)
  21 + {
  22 + av_log(nullptr, AV_LOG_ERROR, "Failed to create specified HW device ! \n");
  23 + return nullptr;
  24 + }
  25 + ctxMap[gpuid] = hw_device_ctx;
  26 + }
  27 + return hw_device_ctx;
  28 +}
0 29 \ No newline at end of file
... ...
check_tool/FFCuContextManager.h 0 → 100644
  1 +
  2 +#include<map>
  3 +#include<string>
  4 +
  5 +extern "C"
  6 +{
  7 + #include <libavcodec/avcodec.h>
  8 + #include <libavdevice/avdevice.h>
  9 + #include <libavformat/avformat.h>
  10 + #include <libavfilter/avfilter.h>
  11 + #include <libavutil/avutil.h>
  12 + #include <libavutil/pixdesc.h>
  13 + #include <libswscale/swscale.h>
  14 +}
  15 +
  16 +using namespace std;
  17 +
  18 +class FFCuContextManager{
  19 +public:
  20 + static FFCuContextManager* getInstance(){
  21 + static FFCuContextManager* singleton = nullptr;
  22 + if (singleton == nullptr){
  23 + singleton = new FFCuContextManager();
  24 + }
  25 + return singleton;
  26 + }
  27 +
  28 + AVBufferRef *getCuCtx(string gpuid);
  29 +
  30 +private:
  31 + FFCuContextManager(){}
  32 + ~FFCuContextManager();
  33 +
  34 +private:
  35 + map<string,AVBufferRef *> ctxMap;
  36 +
  37 +};
0 38 \ No newline at end of file
... ...
check_tool/Makefile 0 → 100644
  1 +
  2 +XX = g++
  3 +NVCC = nvcc
  4 +
  5 +PROJECT_ROOT= /mnt/e/fiss/FFNvDecoder
  6 +
  7 +DEPEND_DIR = $(PROJECT_ROOT)/bin
  8 +SRC_ROOT = $(PROJECT_ROOT)/check_tool
  9 +CUDA_ROOT = /usr/local/cuda
  10 +
  11 +TARGET= $(DEPEND_DIR)/lib/check_tool
  12 +
  13 +
  14 +INCLUDE= -I $(DEPEND_DIR)/include \
  15 + -I $(CUDA_ROOT)/include \
  16 + -I $(SRC_ROOT)\
  17 +
  18 +LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \
  19 + -L $(CUDA_ROOT)/lib64 -lcudart -lcurand -lcublas -lnvjpeg \
  20 + -L /usr/lib/wsl/lib -lcuda -lnvcuvid\
  21 +
  22 +CFLAGS= -g -fPIC -O0 $(INCLUDE) -pthread -lrt -lz -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl
  23 + # -DUNICODE -D_UNICODE
  24 +
  25 +NFLAGS_LIB=-g -c -shared -Xcompiler -fPIC -Xcompiler -fvisibility=hidden
  26 +NFLAGS = $(NFLAGS_LIB) $(INCLUDE) -std=c++11
  27 +
  28 +SRCS:=$(wildcard $(SRC_ROOT)/*.cpp)
  29 +OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))
  30 +
  31 +CU_SOURCES = $(wildcard ${SRC_ROOT}/*.cu)
  32 +CU_OBJS = $(patsubst %.cu, %.o, $(notdir $(CU_SOURCES)))
  33 +
  34 +
  35 +$(TARGET):$(OBJS) $(CU_OBJS)
  36 + rm -f $(TARGET)
  37 + $(XX) -o $@ $^ $(CFLAGS) $(LIBSPATH) $(LIBS) -Wwrite-strings
  38 + rm -f *.o
  39 +
  40 +%.o:$(SRC_ROOT)/%.cpp
  41 + $(XX) $(CFLAGS) -c $<
  42 +
  43 +%.o:$(SRC_ROOT)/%.cu
  44 + @echo "#######################CU_OBJS:$@###############"
  45 + $(NVCC) $(NFLAGS) -o $@ $<
  46 +
  47 +clean:
  48 + rm -f *.o $(TARGET)
  49 +
  50 +
... ...
check_tool/check_tool.cpp 0 → 100644
  1 +#include"check_tool.h"
  2 +
  3 +#include "FFCuContextManager.h"
  4 +
  5 +extern "C"
  6 +{
  7 + #include <libavcodec/avcodec.h>
  8 + #include <libavdevice/avdevice.h>
  9 + #include <libavformat/avformat.h>
  10 + #include <libavfilter/avfilter.h>
  11 + #include <libavutil/avutil.h>
  12 + #include <libavutil/pixdesc.h>
  13 + #include <libswscale/swscale.h>
  14 + #include <libavutil/imgutils.h>
  15 +}
  16 +
  17 +#include <chrono>
  18 +
  19 +static AVPixelFormat get_hw_format(AVCodecContext *avctx, const AVPixelFormat *pix_fmts){
  20 +
  21 + const AVPixelFormat *p;
  22 +
  23 + for (p = pix_fmts; *p != -1; p++) {
  24 + if (*p == AV_PIX_FMT_CUDA)
  25 + return *p;
  26 + }
  27 +
  28 + av_log(nullptr, AV_LOG_ERROR, "Failed to get HW surface format. \n");
  29 + return AV_PIX_FMT_NONE;
  30 +}
  31 +
  32 +static long long get_cur_time(){
  33 + // 获取操作系统当前时间点(精确到微秒)
  34 + chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro
  35 + = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
  36 + // (微秒精度的)时间点 => (微秒精度的)时间戳
  37 + time_t currentTime = tpMicro.time_since_epoch().count();
  38 +
  39 + return (long long )currentTime;
  40 +}
  41 +
  42 +void evalQuality(const string& uri, const char* gpuid){
  43 + AVFormatContext* ifmt_ctx = nullptr;
  44 + AVCodecContext* codec_ctx = nullptr;
  45 + AVCodec *decoder = nullptr;
  46 + AVCodec* codec = nullptr;
  47 + AVPacket* pkt = nullptr;
  48 + int video_index = -1;
  49 + AVStream* st = nullptr;
  50 + SwsContext *img_convert_ctx = nullptr;
  51 + uint8_t *buffer = nullptr;
  52 + int numBytes = 0;
  53 +
  54 + long start_time = 0;
  55 + long end_time = 0;
  56 + long s_time = 0;
  57 + long e_time = 0;
  58 + long long sum = 0;
  59 + double avg_time = 0.0;
  60 +
  61 + int sep = 0;
  62 +
  63 + string cuvid_dec_name = "" ;
  64 + FFCuContextManager* pCtxMgr = FFCuContextManager::getInstance();
  65 + AVDictionary *op = nullptr;
  66 + AVBufferRef *hw_device_ctx = nullptr;
  67 +
  68 +
  69 + avformat_network_init();
  70 +
  71 + // 打开输入视频文件
  72 + AVDictionary *options = nullptr;
  73 + av_dict_set( &options, "bufsize", "655360", 0 );
  74 + av_dict_set( &options, "rtsp_transport", "tcp", 0 );
  75 + // av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
  76 + av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
  77 +
  78 + ///打开输入的流
  79 + ifmt_ctx = avformat_alloc_context();
  80 + int ret = avformat_open_input(&ifmt_ctx, uri.c_str(), nullptr, &options);
  81 + if (ret != 0){
  82 + av_log(nullptr, AV_LOG_ERROR, "Couldn't open input stream ! \n");
  83 + goto end_flag ;
  84 + }
  85 +
  86 + //查找流信息
  87 + if (avformat_find_stream_info(ifmt_ctx, nullptr) < 0){
  88 + av_log(nullptr, AV_LOG_ERROR, "Couldn't find stream information ! \n");
  89 + goto end_flag ;
  90 + }
  91 +
  92 + // 查找视频流信息
  93 + video_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
  94 + if (video_index < 0) {
  95 + av_log(nullptr, AV_LOG_ERROR, "Cannot find a video stream in the input file ! \n");
  96 + goto end_flag ;
  97 + }
  98 +
  99 + cuvid_dec_name = string(decoder->name) + "_cuvid";
  100 + codec = avcodec_find_decoder_by_name(cuvid_dec_name.c_str());
  101 + if (!codec){
  102 + av_log(nullptr, AV_LOG_ERROR, "Codec not found ! \n");
  103 + goto end_flag ;
  104 + }
  105 +
  106 + //申请AVCodecContext
  107 + codec_ctx = avcodec_alloc_context3(codec);
  108 + if (!codec_ctx){
  109 + goto end_flag ;
  110 + }
  111 +
  112 + st = ifmt_ctx->streams[video_index];
  113 + if(avcodec_parameters_to_context(codec_ctx, st->codecpar) < 0){
  114 + goto end_flag ;
  115 + }
  116 +
  117 + {
  118 + av_log(nullptr, AV_LOG_INFO, "path: %s \n", ifmt_ctx->url);
  119 + av_log(nullptr, AV_LOG_INFO, "format: %s \n", ifmt_ctx->iformat->name);
  120 + const char* profile = avcodec_profile_name(codec_ctx->codec_id, codec_ctx->profile);
  121 + av_log(nullptr, AV_LOG_INFO, "codec: %s(%s) \n", decoder->name, profile);
  122 + const char* pix_fmt_name = av_get_pix_fmt_name(codec_ctx->pix_fmt);
  123 + av_log(nullptr, AV_LOG_INFO, "pix_fmt_name: %s \n", pix_fmt_name);
  124 + av_log(nullptr, AV_LOG_INFO, "width x height: %dX%d \n", st->codecpar->width, st->codecpar->height);
  125 +
  126 + av_log(NULL, AV_LOG_INFO, "frame_rate: %1.0f ", av_q2d(st->r_frame_rate));
  127 + av_log(NULL, AV_LOG_INFO, " --> reference PPS: %f ms\n", 1/av_q2d(st->r_frame_rate) * 1000);
  128 +
  129 + }
  130 +
  131 + // 设置解码器管理器的像素格式回调函数
  132 + codec_ctx->get_format = get_hw_format;
  133 +
  134 + hw_device_ctx = pCtxMgr->getCuCtx(gpuid);
  135 + if(nullptr == hw_device_ctx){
  136 + av_log(nullptr, AV_LOG_ERROR, "create CUDA context failed ! \n");
  137 + goto end_flag ;
  138 + }
  139 + codec_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
  140 + if (nullptr == codec_ctx->hw_device_ctx){
  141 + goto end_flag ;
  142 + }
  143 +
  144 + // 打开解码器流
  145 + av_dict_set( &op, "gpu", gpuid, 0 );
  146 + if (avcodec_open2(codec_ctx, codec, &op) < 0) {
  147 + av_log(nullptr, AV_LOG_ERROR, "Failed to open codec for stream ! \n");
  148 + goto end_flag ;
  149 + }
  150 +
  151 + s_time = get_cur_time();
  152 + start_time = get_cur_time();
  153 + pkt = av_packet_alloc();
  154 + while (av_read_frame(ifmt_ctx, pkt) >= 0){
  155 + end_time = get_cur_time();
  156 + sum ++ ;
  157 + sep ++ ;
  158 + if(end_time - start_time > 1000){
  159 + avg_time = double(end_time - start_time) / sep;
  160 + start_time = get_cur_time();
  161 + sep = 0;
  162 + av_log(nullptr, AV_LOG_INFO, "PPS: %f ms\n", avg_time);
  163 + }
  164 + av_packet_unref(pkt);
  165 + }
  166 +
  167 + e_time = get_cur_time();
  168 + avg_time = double(e_time - s_time) / sum;
  169 + av_log(nullptr, AV_LOG_INFO, "TOOTAL PPS: %f ms\n", avg_time);
  170 +
  171 +end_flag:
  172 + if (codec_ctx != nullptr){
  173 + avcodec_close(codec_ctx);
  174 + avcodec_free_context(&codec_ctx);
  175 + }
  176 +
  177 + if (ifmt_ctx != nullptr){
  178 + avformat_close_input(&ifmt_ctx);
  179 + }
  180 +
  181 + if (pkt != nullptr){
  182 + av_packet_free(&pkt);
  183 + }
  184 +}
0 185 \ No newline at end of file
... ...
check_tool/check_tool.h 0 → 100644
  1 +#include<string>
  2 +
  3 +using namespace std;
  4 +
  5 +void evalQuality(const string& uri, const char* gpuid);
0 6 \ No newline at end of file
... ...
check_tool/main.cpp 0 → 100644
  1 +#include"check_tool.h"
  2 +
  3 +#include <cuda.h>
  4 +
  5 +#include<iostream>
  6 +
  7 +using namespace std;
  8 +
  9 +
  10 +#define checkCudaErrors(S) do {CUresult status; \
  11 + status = S; \
  12 + if (status != CUDA_SUCCESS ) {std::cout << __LINE__ <<" checkCudaErrors - status = " << status << std::endl; \
  13 + exit(EXIT_FAILURE);}\
  14 + } while (false)
  15 +
  16 +
  17 +
  18 +int CheckCUDAProperty( int devId )
  19 +{
  20 + cuInit(0);
  21 +
  22 + CUdevice dev = devId;
  23 + size_t memSize = 0;
  24 + char devName[256] = {0};
  25 + int major = 0, minor = 0;
  26 + CUresult rlt = CUDA_SUCCESS;
  27 +
  28 + checkCudaErrors(cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, dev));
  29 + checkCudaErrors(cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, dev));
  30 +
  31 + checkCudaErrors( cuDeviceGetName(devName, sizeof( devName ), dev) );
  32 +
  33 + printf( "Using GPU Device %d: %s has SM %d.%d compute capability\n",
  34 + dev, devName, major, minor );
  35 +
  36 + rlt = cuDeviceTotalMem( &memSize, dev );
  37 + checkCudaErrors( rlt );
  38 +
  39 + printf( "Total amount of global memory: %4.4f MB\n",
  40 + (float)memSize / ( 1024 * 1024 ) );
  41 +
  42 + return 0;
  43 +}
  44 +
  45 +
  46 +int main(int argc, char *argv[]) {
  47 + printf("start \n");
  48 + if (argc != 3) {
  49 + fprintf(stderr, "./xxx uri gpu_id\n");
  50 + return -1;
  51 + }
  52 +
  53 + char* uri = argv[1];
  54 + char* gpuid = argv[2];
  55 +
  56 + CheckCUDAProperty(atoi(gpuid));
  57 +
  58 + evalQuality(uri,gpuid);
  59 +
  60 + return 0;
  61 +}
0 62 \ No newline at end of file
... ...