Commit 7319ea36117b3270fc33661b77cc77cd8a92b0b3

Authored by Hu Chunming
1 parent e41a52bb

多显卡设置

src/FFNvDecoder.cpp
... ... @@ -125,7 +125,6 @@ bool FFNvDecoder::init(const string& path)
125 125 cout << "Failed to create specified HW device.";
126 126 return false;
127 127 }
128   - avctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
129 128  
130 129 // 打开解码器流
131 130 if (avcodec_open2(avctx, decoder, nullptr) < 0) {
... ... @@ -136,6 +135,79 @@ bool FFNvDecoder::init(const string&amp; path)
136 135 return true;
137 136 }
138 137  
  138 +bool FFNvDecoder::init2(FFDecConfig& cfg)
  139 +{
  140 + m_cfg = cfg;
  141 +
  142 + fstream infile(cfg.uri);
  143 + if (infile.is_open()){
  144 + m_bReal = false;
  145 + infile.close();
  146 + }else {
  147 + m_bReal = true;
  148 + }
  149 +
  150 +
  151 +
  152 + // 打开输入视频文件
  153 + AVDictionary *options = nullptr;
  154 + av_dict_set( &options, "bufsize", "655360", 0 );
  155 + av_dict_set( &options, "rtsp_transport", cfg.force_tcp ? "tcp" : "udp", 0 );
  156 + // av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s
  157 + av_dict_set( &options, "stimeout", "3000000", 0 );
  158 +
  159 + av_register_all();
  160 + avformat_network_init();
  161 +
  162 + fmt_ctx = avformat_alloc_context();
  163 + const char* input_file = cfg.uri.c_str();
  164 + if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
  165 + cout << "Cannot open input file" << input_file;
  166 + return false;
  167 + }
  168 +
  169 + // 查找流信息
  170 + if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
  171 + cout << "Cannot find input stream information";
  172 + return false;
  173 + }
  174 +
  175 + // 查找视频流信息
  176 + AVCodec *decoder = nullptr;
  177 + stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
  178 + if (stream_index < 0) {
  179 + cout << "Cannot find a video stream in the input file";
  180 + return false;
  181 + }
  182 +
  183 +
  184 + string cuvid_dec_name = string(decoder->name) + "_cuvid";
  185 + AVCodec *vcodec = avcodec_find_decoder_by_name(cuvid_dec_name.c_str());
  186 + if (!(avctx = avcodec_alloc_context3(vcodec)))
  187 + return (bool)AVERROR(ENOMEM);
  188 +
  189 + // 得到视频流对象
  190 + stream = fmt_ctx->streams[stream_index];
  191 + if (avcodec_parameters_to_context(avctx, stream->codecpar) < 0)
  192 + return false;
  193 +
  194 + avctx->opaque = this;
  195 + // 设置解码器管理器的像素格式回调函数
  196 + avctx->get_format = get_hw_format;
  197 +
  198 + hw_pix_fmt = AV_PIX_FMT_CUDA;
  199 +
  200 + // 打开解码器流
  201 + AVDictionary *op = nullptr;
  202 + av_dict_set( &op, "gpu", cfg.gpuid.c_str(), 0 );
  203 + if (avcodec_open2(avctx, vcodec, &op) < 0) {
  204 + cout << "Failed to open codec for stream" << stream_index;
  205 + return false;
  206 + }
  207 +
  208 + return true;
  209 +}
  210 +
139 211 void FFNvDecoder::start(){
140 212  
141 213 m_bRunning = true;
... ... @@ -210,7 +282,7 @@ void FFNvDecoder::decode_thread()
210 282 result = avcodec_send_packet(avctx, pkt);
211 283 if (result < 0)
212 284 {
213   - cout << "Failed to send pkt" << result << endl;
  285 + cout << "Failed to send pkt:" << result << endl;
214 286 continue;
215 287 }
216 288  
... ... @@ -222,16 +294,6 @@ void FFNvDecoder::decode_thread()
222 294 }
223 295  
224 296 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 297 }
236 298 av_packet_unref(pkt);
237 299 }
... ...
src/FFNvDecoder.h
... ... @@ -29,11 +29,20 @@ 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 44 bool init(const string& path);
  45 + bool init2(FFDecConfig& cfg);
37 46 void close();
38 47 void start();
39 48 void pause();
... ... @@ -55,6 +64,7 @@ private:
55 64 public:
56 65 POST_DECODE_CALLBACK post_decoded_cbk;
57 66 const void * m_userPtr;
  67 + FFDecConfig m_cfg;
58 68  
59 69 private:
60 70 AVStream* stream;
... ...
src/FFNvDecoderManager.cpp
... ... @@ -3,8 +3,8 @@
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 +FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig& config){
  7 + int num = decoderMap.count(config.name);
8 8 if (num > 0)
9 9 {
10 10 cout << "已存在name所标记的解码器" << endl;
... ... @@ -17,12 +17,12 @@ FFNvDecoder* FFNvDecoderManager::createDecoder(const char * uri, POST_DECODE_CAL
17 17 return nullptr;
18 18 }
19 19  
20   - bool bRet= dec->init(uri);
  20 + bool bRet= dec->init2(config.cfg);
21 21 if (bRet)
22 22 {
23   - dec->setName(name) ;
24   - dec->post_decoded_cbk = post_decoded_cbk;
25   - decoderMap[name] = dec;
  23 + dec->setName(config.name) ;
  24 + dec->post_decoded_cbk = config.cfg.post_decoded_cbk;
  25 + decoderMap[config.name] = dec;
26 26 return dec;
27 27 }
28 28  
... ...
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);
... ...
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,7 +7,6 @@
7 7  
8 8 unsigned char *pHwRgb = nullptr;
9 9  
10   -
11 10 void postDecoded(const void * userPtr, AVFrame * gpuFrame){
12 11 FFNvDecoder* decoder = (FFNvDecoder*)userPtr;
13 12 if (decoder!= nullptr)
... ... @@ -19,42 +18,77 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){
19 18 cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl;
20 19  
21 20 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
  21 + {
  22 + cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl;
  23 + // cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str()));
  24 + // cudaError_t cudaStatus;
  25 + // if(pHwRgb == nullptr){
  26 + // cuda_common::setColorSpace2( ITU709, 0 );
  27 + // cudaStatus = cudaMalloc((void **)&pHwRgb, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char));
  28 + // }
  29 + // cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb, gpuFrame->width, gpuFrame->height);
  30 + // cudaDeviceSynchronize();
  31 + // if (cudaStatus != cudaSuccess) {
  32 + // cout << "CUDAToBGR failed !!!" << endl;
  33 + // return;
  34 + // }
  35 +
  36 + // string path = "/home/cmhu/FFNvDecoder/" + decoder->m_cfg.gpuid + ".jpg";
  37 + // saveJpeg(path.c_str(), pHwRgb, gpuFrame->width, gpuFrame->height); // 验证 CUDAToRGB
34 38 }
35 39 }
36 40 }
37 41  
38 42 int main(){
39 43  
40   - cuda_common::setColorSpace2( ITU709, 0 );
41   -
42 44 FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance();
43   - // FFNvDecoder* decoder = pDecManager->createDecoder("rtmp://192.168.10.56:1935/objecteye/1",postDecoded,"dec1");
44   - // if (!decoder)
45   - // {
46   - // return 1;
47   - // }
48   - // pDecManager->setUserPtr("dec1", decoder);
49   - // pDecManager->startDecodeByName("dec1");
50   -
51   - FFNvDecoder* dec2 = pDecManager->createDecoder("/home/cmhu/data/duan1.avi",postDecoded,"dec2");
  45 + MgrDecConfig config;
  46 + config.name = "dec1";
  47 + config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
  48 + config.cfg.post_decoded_cbk = postDecoded;
  49 + config.cfg.force_tcp = true;
  50 + config.cfg.gpuid = "1";
  51 + FFNvDecoder* decoder = pDecManager->createDecoder(config);
  52 + if (!decoder)
  53 + {
  54 + return 1;
  55 + }
  56 + pDecManager->setUserPtr(config.name, decoder);
  57 + pDecManager->startDecodeByName(config.name);
  58 +
  59 + config.name = "dec2";
  60 + config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
  61 + config.cfg.gpuid = "2";
  62 + FFNvDecoder* dec2 = pDecManager->createDecoder(config);
52 63 if (!dec2)
53 64 {
54 65 return 1;
55 66 }
56   - pDecManager->setUserPtr("dec2", dec2);
57   - pDecManager->startDecodeByName("dec2");
  67 + pDecManager->setUserPtr(config.name, dec2);
  68 + pDecManager->startDecodeByName(config.name);
  69 +
  70 +
  71 + config.name = "dec0";
  72 + config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
  73 + config.cfg.gpuid = "0";
  74 + FFNvDecoder* dec0 = pDecManager->createDecoder(config);
  75 + if (!dec0)
  76 + {
  77 + return 1;
  78 + }
  79 + pDecManager->setUserPtr(config.name, dec0);
  80 + pDecManager->startDecodeByName(config.name);
  81 +
  82 + config.name = "dec01";
  83 + config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1";
  84 + config.cfg.gpuid = "0";
  85 + FFNvDecoder* dec01 = pDecManager->createDecoder(config);
  86 + if (!dec01)
  87 + {
  88 + return 1;
  89 + }
  90 + pDecManager->setUserPtr(config.name, dec01);
  91 + pDecManager->startDecodeByName(config.name);
58 92  
59 93 // while (getchar() != 'q');
60 94  
... ...