Commit 620bf1e2e6eb9913200219ad165b8dbbb33a8b19

Authored by Hu Chunming
2 parents 58d98527 48330793

Merge branch 'dev-cmhu' into 'master'

Dev cmhu

See merge request !2
src/FFNvDecoder.cpp
@@ -38,6 +38,11 @@ FFNvDecoder::FFNvDecoder() @@ -38,6 +38,11 @@ FFNvDecoder::FFNvDecoder()
38 38
39 m_bPause = false; 39 m_bPause = false;
40 m_bReal = true; 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 FFNvDecoder::~FFNvDecoder() 48 FFNvDecoder::~FFNvDecoder()
@@ -45,9 +50,11 @@ 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 if (infile.is_open()){ 58 if (infile.is_open()){
52 m_bReal = false; 59 m_bReal = false;
53 infile.close(); 60 infile.close();
@@ -55,24 +62,25 @@ bool FFNvDecoder::init(const string& path) @@ -55,24 +62,25 @@ bool FFNvDecoder::init(const string& path)
55 m_bReal = true; 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 AVDictionary *options = nullptr; 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 fmt_ctx = avformat_alloc_context(); 80 fmt_ctx = avformat_alloc_context();
73 - const char* input_file = path.c_str(); 81 + const char* input_file = uri;
74 if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) { 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 return false; 84 return false;
77 } 85 }
78 86
@@ -90,24 +98,9 @@ bool FFNvDecoder::init(const string&amp; path) @@ -90,24 +98,9 @@ bool FFNvDecoder::init(const string&amp; path)
90 return false; 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 return (bool)AVERROR(ENOMEM); 104 return (bool)AVERROR(ENOMEM);
112 105
113 // 得到视频流对象 106 // 得到视频流对象
@@ -119,16 +112,12 @@ bool FFNvDecoder::init(const string&amp; path) @@ -119,16 +112,12 @@ bool FFNvDecoder::init(const string&amp; path)
119 // 设置解码器管理器的像素格式回调函数 112 // 设置解码器管理器的像素格式回调函数
120 avctx->get_format = get_hw_format; 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 cout << "Failed to open codec for stream" << stream_index; 121 cout << "Failed to open codec for stream" << stream_index;
133 return false; 122 return false;
134 } 123 }
@@ -148,6 +137,13 @@ void FFNvDecoder::start(){ @@ -148,6 +137,13 @@ void FFNvDecoder::start(){
148 return (void*)0; 137 return (void*)0;
149 } 138 }
150 ,this); 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 pthread_create(&m_post_decode_thread,0, 148 pthread_create(&m_post_decode_thread,0,
153 [](void* arg) 149 [](void* arg)
@@ -157,13 +153,6 @@ void FFNvDecoder::start(){ @@ -157,13 +153,6 @@ void FFNvDecoder::start(){
157 return (void*)0; 153 return (void*)0;
158 } 154 }
159 ,this); 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 while (m_bRunning) 157 while (m_bRunning)
169 { 158 {
@@ -210,7 +199,7 @@ void FFNvDecoder::decode_thread() @@ -210,7 +199,7 @@ void FFNvDecoder::decode_thread()
210 result = avcodec_send_packet(avctx, pkt); 199 result = avcodec_send_packet(avctx, pkt);
211 if (result < 0) 200 if (result < 0)
212 { 201 {
213 - cout << "Failed to send pkt" << result << endl; 202 + cout << "Failed to send pkt:" << result << endl;
214 continue; 203 continue;
215 } 204 }
216 205
@@ -222,24 +211,41 @@ void FFNvDecoder::decode_thread() @@ -222,24 +211,41 @@ void FFNvDecoder::decode_thread()
222 } 211 }
223 212
224 mFrameQueue.addTail(); 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 av_packet_unref(pkt); 215 av_packet_unref(pkt);
237 } 216 }
238 217
239 m_bRunning = false; 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 cout << "decode thread exited." << endl; 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 void FFNvDecoder::post_decode_thread() 249 void FFNvDecoder::post_decode_thread()
244 { 250 {
245 while (m_bRunning) 251 while (m_bRunning)
@@ -262,21 +268,8 @@ void FFNvDecoder::post_decode_thread() @@ -262,21 +268,8 @@ void FFNvDecoder::post_decode_thread()
262 void FFNvDecoder::close() 268 void FFNvDecoder::close()
263 { 269 {
264 m_bRunning=false; 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,6 +291,11 @@ bool FFNvDecoder::isRunning()
298 return m_bRunning; 291 return m_bRunning;
299 } 292 }
300 293
  294 +bool FFNvDecoder::isFinished()
  295 +{
  296 + return m_bFinished;
  297 +}
  298 +
301 bool FFNvDecoder::getResolution( int &width, int &height ) 299 bool FFNvDecoder::getResolution( int &width, int &height )
302 { 300 {
303 if (avctx != nullptr) 301 if (avctx != nullptr)
src/FFNvDecoder.h
@@ -20,7 +20,7 @@ using namespace std; @@ -20,7 +20,7 @@ using namespace std;
20 * 接口:DXDECODER_CALLBACK 20 * 接口:DXDECODER_CALLBACK
21 * 功能:解码数据回调接口 21 * 功能:解码数据回调接口
22 * 参数:const dx_void * userPtr 用户自定义数据 22 * 参数:const dx_void * userPtr 用户自定义数据
23 -* AVFrame * gpuFrame 解码结果帧数据 23 +* AVFrame * gpuFrame 解码结果帧数据,在设置的对应的gpu上,要十分注意这一点,尤其是多线程情况
24 * 返回:无 24 * 返回:无
25 * 备注:当解码库数据源为实时流时(RTSP/GB28181),本接 25 * 备注:当解码库数据源为实时流时(RTSP/GB28181),本接
26 * 口内不可进行阻塞/耗时操作。当解码库数据源为 26 * 口内不可进行阻塞/耗时操作。当解码库数据源为
@@ -29,17 +29,26 @@ using namespace std; @@ -29,17 +29,26 @@ using namespace std;
29 **************************************************/ 29 **************************************************/
30 typedef void(*POST_DECODE_CALLBACK)(const void * userPtr, AVFrame * gpuFrame); 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 class FFNvDecoder{ 40 class FFNvDecoder{
33 public: 41 public:
34 FFNvDecoder(); 42 FFNvDecoder();
35 ~FFNvDecoder(); 43 ~FFNvDecoder();
36 - bool init(const string& path); 44 + bool init(FFDecConfig& cfg);
37 void close(); 45 void close();
38 void start(); 46 void start();
39 void pause(); 47 void pause();
40 void resume(); 48 void resume();
41 49
42 bool isRunning(); 50 bool isRunning();
  51 + bool isFinished();
43 bool getResolution( int &width, int &height ); 52 bool getResolution( int &width, int &height );
44 53
45 void setName(string nm); 54 void setName(string nm);
@@ -51,10 +60,13 @@ public: @@ -51,10 +60,13 @@ public:
51 private: 60 private:
52 void decode_thread(); 61 void decode_thread();
53 void post_decode_thread(); 62 void post_decode_thread();
  63 + bool init(const char* uri, const char* gpuid, bool force_tcp);
  64 + void decode_finished();
54 65
55 public: 66 public:
56 POST_DECODE_CALLBACK post_decoded_cbk; 67 POST_DECODE_CALLBACK post_decoded_cbk;
57 const void * m_userPtr; 68 const void * m_userPtr;
  69 + FFDecConfig m_cfg;
58 70
59 private: 71 private:
60 AVStream* stream; 72 AVStream* stream;
@@ -67,6 +79,7 @@ private: @@ -67,6 +79,7 @@ private:
67 pthread_t m_post_decode_thread; 79 pthread_t m_post_decode_thread;
68 80
69 bool m_bRunning; 81 bool m_bRunning;
  82 + bool m_bFinished;
70 string name; 83 string name;
71 84
72 bool m_bPause; 85 bool m_bPause;
src/FFNvDecoderManager.cpp
@@ -3,8 +3,12 @@ @@ -3,8 +3,12 @@
3 3
4 using namespace std; 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 if (num > 0) 12 if (num > 0)
9 { 13 {
10 cout << "已存在name所标记的解码器" << endl; 14 cout << "已存在name所标记的解码器" << endl;
@@ -17,12 +21,12 @@ FFNvDecoder* FFNvDecoderManager::createDecoder(const char * uri, POST_DECODE_CAL @@ -17,12 +21,12 @@ FFNvDecoder* FFNvDecoderManager::createDecoder(const char * uri, POST_DECODE_CAL
17 return nullptr; 21 return nullptr;
18 } 22 }
19 23
20 - bool bRet= dec->init(uri); 24 + bool bRet= dec->init(config.cfg);
21 if (bRet) 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 return dec; 30 return dec;
27 } 31 }
28 32
@@ -126,11 +130,26 @@ void FFNvDecoderManager::closeAllDecoder() @@ -126,11 +130,26 @@ void FFNvDecoderManager::closeAllDecoder()
126 { 130 {
127 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){ 131 for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){
128 iter->second->close(); 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 int FFNvDecoderManager::count() 149 int FFNvDecoderManager::count()
133 { 150 {
  151 + closeAllFinishedDecoder();
  152 +
134 return decoderMap.size(); 153 return decoderMap.size();
135 } 154 }
136 155
@@ -172,10 +191,27 @@ bool FFNvDecoderManager::resumeDecoder(string name) @@ -172,10 +191,27 @@ bool FFNvDecoderManager::resumeDecoder(string name)
172 return false; 191 return false;
173 } 192 }
174 193
175 -bool FFNvDecoderManager::isSurport(const char* uri) 194 +bool FFNvDecoderManager::isSurport(FFDecConfig& cfg)
176 { 195 {
177 FFNvDecoder dec; 196 FFNvDecoder dec;
178 - bool bRet = dec.init(uri); 197 + bool bRet = dec.init(cfg);
179 dec.close(); 198 dec.close();
180 return bRet; 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 \ No newline at end of file 218 \ No newline at end of file
src/FFNvDecoderManager.h
@@ -5,6 +5,12 @@ @@ -5,6 +5,12 @@
5 5
6 using namespace std; 6 using namespace std;
7 7
  8 +struct MgrDecConfig
  9 +{
  10 + FFDecConfig cfg;
  11 + string name{""};
  12 +};
  13 +
8 class FFNvDecoderManager{ 14 class FFNvDecoderManager{
9 public: 15 public:
10 static FFNvDecoderManager* getInstance(){ 16 static FFNvDecoderManager* getInstance(){
@@ -20,7 +26,7 @@ public: @@ -20,7 +26,7 @@ public:
20 closeAllDecoder(); 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 void setUserPtr(string name, const void * userPtr); 30 void setUserPtr(string name, const void * userPtr);
25 31
26 FFNvDecoder* getDecoderByName(const string name); 32 FFNvDecoder* getDecoderByName(const string name);
@@ -31,11 +37,16 @@ public: @@ -31,11 +37,16 @@ public:
31 37
32 bool closeDecoderByName(string name); 38 bool closeDecoderByName(string name);
33 void closeAllDecoder(); 39 void closeAllDecoder();
  40 + void closeAllFinishedDecoder();
  41 +
  42 + bool removeDecoderByName(string name);
34 43
35 bool pauseDecoder(string name); 44 bool pauseDecoder(string name);
36 bool resumeDecoder(string name); 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 int count(); 51 int count();
41 52
src/NV12ToRGB.cu
@@ -301,26 +301,6 @@ namespace cuda_common @@ -301,26 +301,6 @@ namespace cuda_common
301 fprintf(stderr, "cudaMemcpyToSymbol failed: %s\n", cudaGetErrorString(cudaStatus)); 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 return cudaStatus; 304 return cudaStatus;
325 } 305 }
326 306
src/NvJpegEncoder.cpp
1 #include "NvJpegEncoder.h" 1 #include "NvJpegEncoder.h"
2 2
3 -#include <nvjpeg.h>  
4 -  
5 #include <fstream> 3 #include <fstream>
6 #include <vector> 4 #include <vector>
7 #include <iostream> 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 int saveJpeg(const char * filepath, unsigned char* d_srcBGR, int width, int height) 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 input.channel[0] = d_srcBGR; 37 input.channel[0] = d_srcBGR;
36 input.pitch[0] = image_width * 3; 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 \ No newline at end of file 91 \ No newline at end of file
src/NvJpegEncoder.h
1 - 1 +#include <nvjpeg.h>
2 2
3 int saveJpeg(const char * filepath, unsigned char* d_srcBGR, int width, int height); 3 int saveJpeg(const char * filepath, unsigned char* d_srcBGR, int width, int height);
4 \ No newline at end of file 4 \ No newline at end of file
src/cuda_kernels.h
@@ -19,7 +19,6 @@ typedef enum @@ -19,7 +19,6 @@ typedef enum
19 namespace cuda_common 19 namespace cuda_common
20 { 20 {
21 cudaError_t setColorSpace2(e_ColorSpace CSC, float hue); 21 cudaError_t setColorSpace2(e_ColorSpace CSC, float hue);
22 - cudaError_t showHueCSC3();  
23 22
24 cudaError_t NV12ToRGBnot(CUdeviceptr d_srcNV12, size_t nSourcePitch, unsigned char* d_dstRGB, int width, int height); 23 cudaError_t NV12ToRGBnot(CUdeviceptr d_srcNV12, size_t nSourcePitch, unsigned char* d_dstRGB, int width, int height);
25 cudaError_t CUDAToBGR(CUdeviceptr dataY, CUdeviceptr dataUV, size_t pitchY, size_t pitchUV, unsigned char* d_dstRGB, int width, int height); 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,54 +7,103 @@
7 7
8 unsigned char *pHwRgb = nullptr; 8 unsigned char *pHwRgb = nullptr;
9 9
10 - 10 +/**
  11 + * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况
  12 + * */
11 void postDecoded(const void * userPtr, AVFrame * gpuFrame){ 13 void postDecoded(const void * userPtr, AVFrame * gpuFrame){
12 FFNvDecoder* decoder = (FFNvDecoder*)userPtr; 14 FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
13 if (decoder!= nullptr) 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 cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl; 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 if (gpuFrame->format == AV_PIX_FMT_CUDA) 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 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); 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 if (!dec2) 78 if (!dec2)
53 { 79 {
54 return 1; 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 // while (getchar() != 'q'); 108 // while (getchar() != 'q');
60 109