Merged
Merge Request #2 · created by Hu Chunming


Dev cmhu


From dev-cmhu into master

Merged by Hu Chunming

1 participants


src/FFNvDecoder.cpp
... ... @@ -38,6 +38,11 @@ FFNvDecoder::FFNvDecoder()
38 38  
39 39 m_bPause = false;
40 40 m_bReal = true;
  41 +
  42 + m_decode_thread = 0;
  43 + m_post_decode_thread = 0;
  44 +
  45 + m_bFinished = false;
41 46 }
42 47  
43 48 FFNvDecoder::~FFNvDecoder()
... ... @@ -45,9 +50,11 @@ FFNvDecoder::~FFNvDecoder()
45 50  
46 51 }
47 52  
48   -bool FFNvDecoder::init(const string& path)
  53 +bool FFNvDecoder::init(FFDecConfig& cfg)
49 54 {
50   - fstream infile(path);
  55 + m_cfg = cfg;
  56 +
  57 + fstream infile(cfg.uri);
51 58 if (infile.is_open()){
52 59 m_bReal = false;
53 60 infile.close();
... ... @@ -55,24 +62,25 @@ bool FFNvDecoder::init(const string& path)
55 62 m_bReal = true;
56 63 }
57 64  
58   - // 查找对应的硬件解码设备
59   - const char* device_name = "cuda";
60   - AVHWDeviceType hw_device_type = av_hwdevice_find_type_by_name(device_name);
61   - if (hw_device_type == AV_HWDEVICE_TYPE_NONE) {
62   - while ((hw_device_type = av_hwdevice_iterate_types(hw_device_type)) != AV_HWDEVICE_TYPE_NONE)
63   - cout << av_hwdevice_get_type_name(hw_device_type);
64   - return false;
65   - }
  65 + return init(cfg.uri.c_str(), cfg.gpuid.c_str(),cfg.force_tcp);
  66 +}
  67 +
  68 +bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp)
  69 +{
  70 + av_register_all();
  71 + avformat_network_init();
66 72  
67 73 // 打开输入视频文件
68 74 AVDictionary *options = nullptr;
69   - av_dict_set( &options, "bufsize", "1024000", 0 );
70   - av_dict_set( &options, "rtsp_transport", "tcp", 0 );
71   - av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
  75 + av_dict_set( &options, "bufsize", "655360", 0 );
  76 + av_dict_set( &options, "rtsp_transport", force_tcp ? "tcp" : "udp", 0 );
  77 + // av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
  78 + av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
  79 +
72 80 fmt_ctx = avformat_alloc_context();
73   - const char* input_file = path.c_str();
  81 + const char* input_file = uri;
74 82 if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
75   - cout << "Cannot open input file" << input_file;
  83 + cout << "Cannot open input file: " << input_file;
76 84 return false;
77 85 }
78 86  
... ... @@ -90,24 +98,9 @@ bool FFNvDecoder::init(const string&amp; path)
90 98 return false;
91 99 }
92 100  
93   - // 判断硬件解码设备是否兼容视频解码器
94   - for (int i = 0;; i++) {
95   - const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i);
96   - if (!config) {
97   - cout << "Decoder does not support device hw_device_type"
98   - << decoder->name << av_hwdevice_get_type_name(hw_device_type);
99   - return false;
100   - }
101   - // 得到硬件解码像素格式
102   - if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
103   - config->device_type == hw_device_type) {
104   - hw_pix_fmt = config->pix_fmt;
105   - break;
106   - }
107   - }
108   -
109   - // 得到解码器管理器
110   - if (!(avctx = avcodec_alloc_context3(decoder)))
  101 + string cuvid_dec_name = string(decoder->name) + "_cuvid";
  102 + AVCodec *vcodec = avcodec_find_decoder_by_name(cuvid_dec_name.c_str());
  103 + if (!(avctx = avcodec_alloc_context3(vcodec)))
111 104 return (bool)AVERROR(ENOMEM);
112 105  
113 106 // 得到视频流对象
... ... @@ -119,16 +112,12 @@ bool FFNvDecoder::init(const string&amp; path)
119 112 // 设置解码器管理器的像素格式回调函数
120 113 avctx->get_format = get_hw_format;
121 114  
122   - // 初始化硬件解码器
123   - AVBufferRef *hw_device_ctx = nullptr;
124   - if (av_hwdevice_ctx_create(&hw_device_ctx, hw_device_type, nullptr, nullptr, 0) < 0) {
125   - cout << "Failed to create specified HW device.";
126   - return false;
127   - }
128   - avctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
  115 + hw_pix_fmt = AV_PIX_FMT_CUDA;
129 116  
130 117 // 打开解码器流
131   - if (avcodec_open2(avctx, decoder, nullptr) < 0) {
  118 + AVDictionary *op = nullptr;
  119 + av_dict_set( &op, "gpu", gpuid, 0 );
  120 + if (avcodec_open2(avctx, vcodec, &op) < 0) {
132 121 cout << "Failed to open codec for stream" << stream_index;
133 122 return false;
134 123 }
... ... @@ -148,6 +137,13 @@ void FFNvDecoder::start(){
148 137 return (void*)0;
149 138 }
150 139 ,this);
  140 +}
  141 +
  142 +void FFNvDecoder::decode_thread()
  143 +{
  144 + AVPacket* pkt ;
  145 + pkt = av_packet_alloc();
  146 + av_init_packet( pkt );
151 147  
152 148 pthread_create(&m_post_decode_thread,0,
153 149 [](void* arg)
... ... @@ -157,13 +153,6 @@ void FFNvDecoder::start(){
157 153 return (void*)0;
158 154 }
159 155 ,this);
160   -}
161   -
162   -void FFNvDecoder::decode_thread()
163   -{
164   - AVPacket* pkt ;
165   - pkt = av_packet_alloc();
166   - av_init_packet( pkt );
167 156  
168 157 while (m_bRunning)
169 158 {
... ... @@ -210,7 +199,7 @@ void FFNvDecoder::decode_thread()
210 199 result = avcodec_send_packet(avctx, pkt);
211 200 if (result < 0)
212 201 {
213   - cout << "Failed to send pkt" << result << endl;
  202 + cout << "Failed to send pkt:" << result << endl;
214 203 continue;
215 204 }
216 205  
... ... @@ -222,24 +211,41 @@ void FFNvDecoder::decode_thread()
222 211 }
223 212  
224 213 mFrameQueue.addTail();
225   -
226   - // if (gpuFrame->format == hw_pix_fmt)
227   - // {
228   - // /* retrieve data from GPU to CPU */
229   - // if (av_hwframe_transfer_data(pong_frame, gpuFrame, 0) < 0)
230   - // {
231   - // cout << "Failed to transfer the data to system memory";
232   - // return;
233   - // }
234   - // }
235 214 }
236 215 av_packet_unref(pkt);
237 216 }
238 217  
239 218 m_bRunning = false;
  219 +
  220 + if (m_post_decode_thread != 0)
  221 + {
  222 + pthread_join(m_post_decode_thread,0);
  223 + }
  224 +
  225 + decode_finished();
  226 +
240 227 cout << "decode thread exited." << endl;
241 228 }
242 229  
  230 +void FFNvDecoder::decode_finished()
  231 +{
  232 + if (avctx)
  233 + {
  234 + if (avctx->hw_device_ctx)
  235 + {
  236 + av_buffer_unref(&avctx->hw_device_ctx);
  237 + }
  238 + avcodec_free_context(&avctx);
  239 + }
  240 +
  241 + if (fmt_ctx)
  242 + {
  243 + avformat_close_input(&fmt_ctx);
  244 + }
  245 +
  246 + m_bFinished = true;
  247 +}
  248 +
243 249 void FFNvDecoder::post_decode_thread()
244 250 {
245 251 while (m_bRunning)
... ... @@ -262,21 +268,8 @@ void FFNvDecoder::post_decode_thread()
262 268 void FFNvDecoder::close()
263 269 {
264 270 m_bRunning=false;
265   - pthread_join(m_decode_thread,0);
266   - pthread_join(m_post_decode_thread,0);
267   -
268   - if (avctx)
269   - {
270   - if (avctx->hw_device_ctx)
271   - {
272   - av_buffer_unref(&avctx->hw_device_ctx);
273   - }
274   - avcodec_free_context(&avctx);
275   - }
276   -
277   - if (fmt_ctx)
278   - {
279   - avformat_close_input(&fmt_ctx);
  271 + if(m_decode_thread != 0){
  272 + pthread_join(m_decode_thread,0);
280 273 }
281 274 }
282 275  
... ... @@ -298,6 +291,11 @@ bool FFNvDecoder::isRunning()
298 291 return m_bRunning;
299 292 }
300 293  
  294 +bool FFNvDecoder::isFinished()
  295 +{
  296 + return m_bFinished;
  297 +}
  298 +
301 299 bool FFNvDecoder::getResolution( int &width, int &height )
302 300 {
303 301 if (avctx != nullptr)
... ...
src/FFNvDecoder.h
... ... @@ -20,7 +20,7 @@ using namespace std;
20 20 * 接口:DXDECODER_CALLBACK
21 21 * 功能:解码数据回调接口
22 22 * 参数:const dx_void * userPtr 用户自定义数据
23   -* AVFrame * gpuFrame 解码结果帧数据
  23 +* AVFrame * gpuFrame 解码结果帧数据,在设置的对应的gpu上,要十分注意这一点,尤其是多线程情况
24 24 * 返回:无
25 25 * 备注:当解码库数据源为实时流时(RTSP/GB28181),本接
26 26 * 口内不可进行阻塞/耗时操作。当解码库数据源为
... ... @@ -29,17 +29,26 @@ using namespace std;
29 29 **************************************************/
30 30 typedef void(*POST_DECODE_CALLBACK)(const void * userPtr, AVFrame * gpuFrame);
31 31  
  32 +struct FFDecConfig
  33 +{
  34 + string uri;
  35 + POST_DECODE_CALLBACK post_decoded_cbk;
  36 + string gpuid;
  37 + bool force_tcp{true};
  38 +};
  39 +
32 40 class FFNvDecoder{
33 41 public:
34 42 FFNvDecoder();
35 43 ~FFNvDecoder();
36   - bool init(const string& path);
  44 + bool init(FFDecConfig& cfg);
37 45 void close();
38 46 void start();
39 47 void pause();
40 48 void resume();
41 49  
42 50 bool isRunning();
  51 + bool isFinished();
43 52 bool getResolution( int &width, int &height );
44 53  
45 54 void setName(string nm);
... ... @@ -51,10 +60,13 @@ public:
51 60 private:
52 61 void decode_thread();
53 62 void post_decode_thread();
  63 + bool init(const char* uri, const char* gpuid, bool force_tcp);
  64 + void decode_finished();
54 65  
55 66 public:
56 67 POST_DECODE_CALLBACK post_decoded_cbk;
57 68 const void * m_userPtr;
  69 + FFDecConfig m_cfg;
58 70  
59 71 private:
60 72 AVStream* stream;
... ... @@ -67,6 +79,7 @@ private:
67 79 pthread_t m_post_decode_thread;
68 80  
69 81 bool m_bRunning;
  82 + bool m_bFinished;
70 83 string name;
71 84  
72 85 bool m_bPause;
... ...
src/FFNvDecoderManager.cpp
... ... @@ -3,8 +3,12 @@
3 3  
4 4 using namespace std;
5 5  
6   -FFNvDecoder* FFNvDecoderManager::createDecoder(const char * uri, POST_DECODE_CALLBACK post_decoded_cbk, string name){
7   - int num = decoderMap.count(name);
  6 +
  7 +FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig& config){
  8 +
  9 + closeAllFinishedDecoder();
  10 +
  11 + int num = decoderMap.count(config.name);
8 12 if (num > 0)
9 13 {
10 14 cout << "已存在name所标记的解码器" << endl;
... ... @@ -17,12 +21,12 @@ FFNvDecoder* FFNvDecoderManager::createDecoder(const char * uri, POST_DECODE_CAL
17 21 return nullptr;
18 22 }
19 23  
20   - bool bRet= dec->init(uri);
  24 + bool bRet= dec->init(config.cfg);
21 25 if (bRet)
22 26 {
23   - dec->setName(name) ;
24   - dec->post_decoded_cbk = post_decoded_cbk;
25   - decoderMap[name] = dec;
  27 + dec->setName(config.name) ;
  28 + dec->post_decoded_cbk = config.cfg.post_decoded_cbk;
  29 + decoderMap[config.name] = dec;
26 30 return dec;
27 31 }
28 32  
... ... @@ -126,11 +130,26 @@ void FFNvDecoderManager::closeAllDecoder()
126 130 {
127 131 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){
128 132 iter->second->close();
  133 + delete iter->second;
  134 + }
  135 + decoderMap.clear();
  136 +}
  137 +
  138 +void FFNvDecoderManager::closeAllFinishedDecoder()
  139 +{
  140 + for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){
  141 + if (iter->second->isFinished())
  142 + {
  143 + delete iter->second;
  144 + decoderMap.erase(iter);
  145 + }
129 146 }
130 147 }
131 148  
132 149 int FFNvDecoderManager::count()
133 150 {
  151 + closeAllFinishedDecoder();
  152 +
134 153 return decoderMap.size();
135 154 }
136 155  
... ... @@ -172,10 +191,27 @@ bool FFNvDecoderManager::resumeDecoder(string name)
172 191 return false;
173 192 }
174 193  
175   -bool FFNvDecoderManager::isSurport(const char* uri)
  194 +bool FFNvDecoderManager::isSurport(FFDecConfig& cfg)
176 195 {
177 196 FFNvDecoder dec;
178   - bool bRet = dec.init(uri);
  197 + bool bRet = dec.init(cfg);
179 198 dec.close();
180 199 return bRet;
  200 +}
  201 +
  202 +bool FFNvDecoderManager::isRunning(string name){
  203 + if (name.empty())
  204 + {
  205 + cout << "name 为空!"<< endl;
  206 + return false;
  207 + }
  208 +
  209 + auto dec = decoderMap.find(name);
  210 + if (dec != decoderMap.end())
  211 + {
  212 + return dec->second->isRunning();
  213 + }
  214 +
  215 + cout << "没有找到name为" << name << "的解码器!" << endl;
  216 + return false;
181 217 }
182 218 \ No newline at end of file
... ...
src/FFNvDecoderManager.h
... ... @@ -5,6 +5,12 @@
5 5  
6 6 using namespace std;
7 7  
  8 +struct MgrDecConfig
  9 +{
  10 + FFDecConfig cfg;
  11 + string name{""};
  12 +};
  13 +
8 14 class FFNvDecoderManager{
9 15 public:
10 16 static FFNvDecoderManager* getInstance(){
... ... @@ -20,7 +26,7 @@ public:
20 26 closeAllDecoder();
21 27 }
22 28  
23   - FFNvDecoder* createDecoder(const char * uri, POST_DECODE_CALLBACK post_decoded_cbk, string name = "");
  29 + FFNvDecoder* createDecoder(MgrDecConfig& config);
24 30 void setUserPtr(string name, const void * userPtr);
25 31  
26 32 FFNvDecoder* getDecoderByName(const string name);
... ... @@ -31,11 +37,16 @@ public:
31 37  
32 38 bool closeDecoderByName(string name);
33 39 void closeAllDecoder();
  40 + void closeAllFinishedDecoder();
  41 +
  42 + bool removeDecoderByName(string name);
34 43  
35 44 bool pauseDecoder(string name);
36 45 bool resumeDecoder(string name);
37 46  
38   - bool isSurport(const char* uri);
  47 + bool isSurport(FFDecConfig& cfg);
  48 +
  49 + bool isRunning(string name);
39 50  
40 51 int count();
41 52  
... ...
src/NV12ToRGB.cu
... ... @@ -301,26 +301,6 @@ namespace cuda_common
301 301 fprintf(stderr, "cudaMemcpyToSymbol failed: %s\n", cudaGetErrorString(cudaStatus));
302 302 }
303 303  
304   - //showHueCSC();
305   -
306   - return cudaStatus;
307   - }
308   -
309   - cudaError_t showHueCSC3()
310   - {
311   - /*
312   - cudaError_t cudaStatus;
313   -
314   - float data[9];
315   - cudaStatus = cudaMemcpyFromSymbol(data, constHueColorSpaceMat2, sizeof(data));
316   - printf("hueCSC ");
317   - for (int i = 0; i < 9; i++)
318   - {
319   - printf("%f ,", data[i]);
320   - }
321   - printf("\n");
322   -*/
323   - cudaError_t cudaStatus;
324 304 return cudaStatus;
325 305 }
326 306  
... ...
src/NvJpegEncoder.cpp
1 1 #include "NvJpegEncoder.h"
2 2  
3   -#include <nvjpeg.h>
4   -
5 3 #include <fstream>
6 4 #include <vector>
7 5 #include <iostream>
8 6  
9 7  
  8 +#define CHECK_NVJPEG(S) do {nvjpegStatus_t status; \
  9 + status = S; \
  10 + if (status != NVJPEG_STATUS_SUCCESS ) std::cout << __LINE__ <<" CHECK_NVJPEG - status = " << status << std::endl; \
  11 + } while (false)
  12 +
10 13  
11 14 int saveJpeg(const char * filepath, unsigned char* d_srcBGR, int width, int height)
12 15 {
13   - nvjpegHandle_t nvjpeg_handle;
14   - nvjpegEncoderState_t encoder_state;
15   - nvjpegEncoderParams_t encoder_params;
16   -
17   - cudaEvent_t ev_start, ev_end;
18   - cudaEventCreate(&ev_start);
19   - cudaEventCreate(&ev_end);
20   -
21   -
22   - nvjpegImage_t input;
23   - nvjpegInputFormat_t input_format = NVJPEG_INPUT_BGRI;
24   - int image_width = width;
25   - int image_height = height;
26   -
27   - // int channel_size = image_width * image_height;
28   - // for (int i = 0; i < 3; i++)
29   - // {
30   - // input.pitch[i] = image_width;
31   - // (cudaMalloc((void**)&(input.channel[i]), channel_size));
32   - // (cudaMemset(input.channel[i], 50 * 40 * i, channel_size));
33   - // }
  16 + nvjpegHandle_t nvjpeg_handle;
  17 + nvjpegEncoderState_t encoder_state;
  18 + nvjpegEncoderParams_t encoder_params;
  19 +
  20 + cudaEvent_t ev_start, ev_end;
  21 + cudaEventCreate(&ev_start);
  22 + cudaEventCreate(&ev_end);
  23 +
  24 + nvjpegImage_t input;
  25 + nvjpegInputFormat_t input_format = NVJPEG_INPUT_BGRI;
  26 + int image_width = width;
  27 + int image_height = height;
  28 +
  29 + // int channel_size = image_width * image_height;
  30 + // for (int i = 0; i < 3; i++)
  31 + // {
  32 + // input.pitch[i] = image_width;
  33 + // (cudaMalloc((void**)&(input.channel[i]), channel_size));
  34 + // (cudaMemset(input.channel[i], 50 * 40 * i, channel_size));
  35 + // }
34 36  
35 37 input.channel[0] = d_srcBGR;
36 38 input.pitch[0] = image_width * 3;
37 39  
38   - nvjpegBackend_t backend = NVJPEG_BACKEND_DEFAULT;
39   -
40   - nvjpegCreate(backend, nullptr, &nvjpeg_handle);
41   -
42   - nvjpegEncoderParamsCreate(nvjpeg_handle, &encoder_params, NULL);
43   - nvjpegEncoderStateCreate(nvjpeg_handle, &encoder_state, NULL);
44   -
45   - // set params
46   - nvjpegEncoderParamsSetEncoding(encoder_params, nvjpegJpegEncoding_t::NVJPEG_ENCODING_PROGRESSIVE_DCT_HUFFMAN, NULL);
47   - nvjpegEncoderParamsSetOptimizedHuffman(encoder_params, 1, NULL);
48   - nvjpegEncoderParamsSetQuality(encoder_params, 70, NULL);
49   - nvjpegEncoderParamsSetSamplingFactors(encoder_params, nvjpegChromaSubsampling_t::NVJPEG_CSS_420, NULL);
50   -
51   - cudaEventRecord(ev_start);
52   - nvjpegEncodeImage(nvjpeg_handle, encoder_state, encoder_params, &input, input_format, image_width, image_height, NULL);
53   - cudaEventRecord(ev_end);
54   -
55   - std::vector<unsigned char> obuffer;
56   - size_t length;
57   - nvjpegEncodeRetrieveBitstream(
58   - nvjpeg_handle,
59   - encoder_state,
60   - NULL,
61   - &length,
62   - NULL);
63   -
64   - obuffer.resize(length);
65   - nvjpegEncodeRetrieveBitstream(
66   - nvjpeg_handle,
67   - encoder_state,
68   - obuffer.data(),
69   - &length,
70   - NULL);
71   -
72   - std::ofstream outputFile(filepath, std::ios::out | std::ios::binary);
73   - outputFile.write(reinterpret_cast<const char *>(obuffer.data()), static_cast<int>(length));
74   -
75   - cudaEventSynchronize(ev_end);
76   -
77   - float ms;
78   - cudaEventElapsedTime(&ms, ev_start, ev_end);
79   - std::cout << "time spend " << ms << " ms" << std::endl;
80   -
81   - return 0;
  40 + nvjpegBackend_t backend = NVJPEG_BACKEND_DEFAULT;
  41 +
  42 + CHECK_NVJPEG(nvjpegCreate(backend, nullptr, &nvjpeg_handle));
  43 +
  44 + CHECK_NVJPEG(nvjpegEncoderParamsCreate(nvjpeg_handle, &encoder_params, NULL));
  45 + CHECK_NVJPEG(nvjpegEncoderStateCreate(nvjpeg_handle, &encoder_state, NULL));
  46 +
  47 + // set params
  48 + CHECK_NVJPEG(nvjpegEncoderParamsSetEncoding(encoder_params, nvjpegJpegEncoding_t::NVJPEG_ENCODING_PROGRESSIVE_DCT_HUFFMAN, NULL));
  49 + CHECK_NVJPEG(nvjpegEncoderParamsSetOptimizedHuffman(encoder_params, 1, NULL));
  50 + CHECK_NVJPEG(nvjpegEncoderParamsSetQuality(encoder_params, 70, NULL));
  51 + CHECK_NVJPEG(nvjpegEncoderParamsSetSamplingFactors(encoder_params, nvjpegChromaSubsampling_t::NVJPEG_CSS_420, NULL));
  52 +
  53 + cudaEventRecord(ev_start);
  54 + CHECK_NVJPEG(nvjpegEncodeImage(nvjpeg_handle, encoder_state, encoder_params, &input, input_format, image_width, image_height, NULL));
  55 + cudaEventRecord(ev_end);
  56 +
  57 + std::vector<unsigned char> obuffer;
  58 + size_t length;
  59 + CHECK_NVJPEG(nvjpegEncodeRetrieveBitstream(
  60 + nvjpeg_handle,
  61 + encoder_state,
  62 + NULL,
  63 + &length,
  64 + NULL));
  65 +
  66 + obuffer.resize(length);
  67 + CHECK_NVJPEG(nvjpegEncodeRetrieveBitstream(
  68 + nvjpeg_handle,
  69 + encoder_state,
  70 + obuffer.data(),
  71 + &length,
  72 + NULL));
  73 +
  74 + cudaEventSynchronize(ev_end);
  75 +
  76 + // 用完销毁,避免显存泄露
  77 + nvjpegEncoderParamsDestroy(encoder_params);
  78 + nvjpegEncoderStateDestroy(encoder_state);
  79 + nvjpegDestroy(nvjpeg_handle);
  80 +
  81 + float ms;
  82 + cudaEventElapsedTime(&ms, ev_start, ev_end);
  83 + std::cout << "time spend " << ms << " ms" << std::endl;
  84 +
  85 + std::ofstream outputFile(filepath, std::ios::out | std::ios::binary);
  86 + outputFile.write(reinterpret_cast<const char *>(obuffer.data()), static_cast<int>(length));
  87 + outputFile.close();
  88 +
  89 + return 0;
82 90 }
83 91 \ No newline at end of file
... ...
src/NvJpegEncoder.h
1   -
  1 +#include <nvjpeg.h>
2 2  
3 3 int saveJpeg(const char * filepath, unsigned char* d_srcBGR, int width, int height);
4 4 \ No newline at end of file
... ...
src/cuda_kernels.h
... ... @@ -19,7 +19,6 @@ typedef enum
19 19 namespace cuda_common
20 20 {
21 21 cudaError_t setColorSpace2(e_ColorSpace CSC, float hue);
22   - cudaError_t showHueCSC3();
23 22  
24 23 cudaError_t NV12ToRGBnot(CUdeviceptr d_srcNV12, size_t nSourcePitch, unsigned char* d_dstRGB, int width, int height);
25 24 cudaError_t CUDAToBGR(CUdeviceptr dataY, CUdeviceptr dataUV, size_t pitchY, size_t pitchUV, unsigned char* d_dstRGB, int width, int height);
... ...
src/main.cpp
... ... @@ -7,54 +7,103 @@
7 7  
8 8 unsigned char *pHwRgb = nullptr;
9 9  
10   -
  10 +/**
  11 + * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况
  12 + * */
11 13 void postDecoded(const void * userPtr, AVFrame * gpuFrame){
12 14 FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
13 15 if (decoder!= nullptr)
14 16 {
15   - cout << decoder->getName() << endl;
16   - const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format);
17   - cout << "pixfmt: " << gpu_pixfmt << endl;
  17 + cout << "decode name: " << decoder->getName() << endl;
  18 + // const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format);
  19 + // cout << "pixfmt: " << gpu_pixfmt << endl;
18 20 cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl;
19   - cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl;
  21 + // cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl;
20 22  
21 23 if (gpuFrame->format == AV_PIX_FMT_CUDA)
22   - {
23   - cudaError_t cudaStatus;
24   - if(pHwRgb == nullptr){
25   - cudaStatus = cudaMalloc((void **)&pHwRgb, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
26   - }
27   - cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb, gpuFrame->width, gpuFrame->height);
28   - cudaDeviceSynchronize();
29   - if (cudaStatus != cudaSuccess) {
30   - cout << "CUDAToBGR failed !!!" << endl;
31   - return;
32   - }
33   - saveJpeg("/home/cmhu/FFNvDecoder/a.jpg", pHwRgb, gpuFrame->width, gpuFrame->height); // 验证 CUDAToRGB
  24 + {
  25 + cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl;
  26 + // cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
  27 + // cudaError_t cudaStatus;
  28 + // if(pHwRgb == nullptr){
  29 + // cuda_common::setColorSpace2( ITU709, 0 );
  30 + // cudaStatus = cudaMalloc((void **)&pHwRgb, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
  31 + // }
  32 + // cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb, gpuFrame->width, gpuFrame->height);
  33 + // cudaDeviceSynchronize();
  34 + // if (cudaStatus != cudaSuccess) {
  35 + // cout << "CUDAToBGR failed !!!" << endl;
  36 + // return;
  37 + // }
  38 +
  39 + // string path = "/home/cmhu/FFNvDecoder/" + decoder->m_cfg.gpuid + ".jpg";
  40 + // saveJpeg(path.c_str(), pHwRgb, gpuFrame->width, gpuFrame->height); // 验证 CUDAToRGB
34 41 }
35 42 }
36 43 }
37 44  
38   -int main(){
  45 +void createDecode(int index){
  46 + FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
  47 + MgrDecConfig config;
  48 + config.name = "dec" + to_string(index);
  49 + config.cfg.uri = "rtsp://176.10.0.4:8554/stream";
  50 + config.cfg.post_decoded_cbk = postDecoded;
  51 + config.cfg.force_tcp = true;
  52 + config.cfg.gpuid = "1";
  53 + FFNvDecoder* decoder = pDecManager->createDecoder(config);
  54 + if (!decoder)
  55 + {
  56 + return ;
  57 + }
  58 + pDecManager->setUserPtr(config.name, decoder);
  59 + pDecManager->startDecodeByName(config.name);
  60 +}
39 61  
40   - cuda_common::setColorSpace2( ITU709, 0 );
  62 +int main(){
41 63  
42 64 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
43   - // FFNvDecoder* decoder = pDecManager->createDecoder("rtmp://192.168.10.56:1935/objecteye/1",postDecoded,"dec1");
44   - // if (!decoder)
  65 +
  66 + // for (size_t i = 0; i < 20; i++)
45 67 // {
46   - // return 1;
  68 + // createDecode(i);
47 69 // }
48   - // pDecManager->setUserPtr("dec1", decoder);
49   - // pDecManager->startDecodeByName("dec1");
50 70  
51   - FFNvDecoder* dec2 = pDecManager->createDecoder("/home/cmhu/data/duan1.avi",postDecoded,"dec2");
  71 + MgrDecConfig config;
  72 + config.name = "dec2";
  73 + config.cfg.uri = "/home/cmhu/data/test.mp4";
  74 + config.cfg.post_decoded_cbk = postDecoded;
  75 + config.cfg.force_tcp = true;
  76 + config.cfg.gpuid = "2";
  77 + FFNvDecoder* dec2 = pDecManager->createDecoder(config);
52 78 if (!dec2)
53 79 {
54 80 return 1;
55 81 }
56   - pDecManager->setUserPtr("dec2", dec2);
57   - pDecManager->startDecodeByName("dec2");
  82 + pDecManager->setUserPtr(config.name, dec2);
  83 + pDecManager->startDecodeByName(config.name);
  84 +
  85 +
  86 + // config.name = "dec0";
  87 + // config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
  88 + // config.cfg.gpuid = "0";
  89 + // FFNvDecoder* dec0 = pDecManager->createDecoder(config);
  90 + // if (!dec0)
  91 + // {
  92 + // return 1;
  93 + // }
  94 + // pDecManager->setUserPtr(config.name, dec0);
  95 + // pDecManager->startDecodeByName(config.name);
  96 +
  97 + // config.name = "dec01";
  98 + // config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
  99 + // config.cfg.gpuid = "0";
  100 + // FFNvDecoder* dec01 = pDecManager->createDecoder(config);
  101 + // if (!dec01)
  102 + // {
  103 + // return 1;
  104 + // }
  105 + // pDecManager->setUserPtr(config.name, dec01);
  106 + // pDecManager->startDecodeByName(config.name);
58 107  
59 108 // while (getchar() != 'q');
60 109  
... ...