diff --git a/src/FFNvDecoder.cpp b/src/FFNvDecoder.cpp index 7f7e47c..6ba885f 100644 --- a/src/FFNvDecoder.cpp +++ b/src/FFNvDecoder.cpp @@ -38,6 +38,11 @@ FFNvDecoder::FFNvDecoder() m_bPause = false; m_bReal = true; + + m_decode_thread = 0; + m_post_decode_thread = 0; + + m_bFinished = false; } FFNvDecoder::~FFNvDecoder() @@ -45,9 +50,11 @@ FFNvDecoder::~FFNvDecoder() } -bool FFNvDecoder::init(const string& path) +bool FFNvDecoder::init(FFDecConfig& cfg) { - fstream infile(path); + m_cfg = cfg; + + fstream infile(cfg.uri); if (infile.is_open()){ m_bReal = false; infile.close(); @@ -55,24 +62,25 @@ bool FFNvDecoder::init(const string& path) m_bReal = true; } - // 查找对应的硬件解码设备 - const char* device_name = "cuda"; - AVHWDeviceType hw_device_type = av_hwdevice_find_type_by_name(device_name); - if (hw_device_type == AV_HWDEVICE_TYPE_NONE) { - while ((hw_device_type = av_hwdevice_iterate_types(hw_device_type)) != AV_HWDEVICE_TYPE_NONE) - cout << av_hwdevice_get_type_name(hw_device_type); - return false; - } + return init(cfg.uri.c_str(), cfg.gpuid.c_str(),cfg.force_tcp); +} + +bool FFNvDecoder::init(const char* uri, const char* gpuid, bool force_tcp) +{ + av_register_all(); + avformat_network_init(); // 打开输入视频文件 AVDictionary *options = nullptr; - av_dict_set( &options, "bufsize", "1024000", 0 ); - av_dict_set( &options, "rtsp_transport", "tcp", 0 ); - av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s + av_dict_set( &options, "bufsize", "655360", 0 ); + av_dict_set( &options, "rtsp_transport", force_tcp ? "tcp" : "udp", 0 ); + // av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s + av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒 + fmt_ctx = avformat_alloc_context(); - const char* input_file = path.c_str(); + const char* input_file = uri; if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) { - cout << "Cannot open input file" << input_file; + cout << "Cannot open input file: " << input_file; return false; } @@ -90,24 +98,9 @@ bool FFNvDecoder::init(const string& path) return false; } - // 判断硬件解码设备是否兼容视频解码器 - for (int i = 0;; i++) { - const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i); - if (!config) { - cout << "Decoder does not support device hw_device_type" - << decoder->name << av_hwdevice_get_type_name(hw_device_type); - return false; - } - // 得到硬件解码像素格式 - if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && - config->device_type == hw_device_type) { - hw_pix_fmt = config->pix_fmt; - break; - } - } - - // 得到解码器管理器 - if (!(avctx = avcodec_alloc_context3(decoder))) + string cuvid_dec_name = string(decoder->name) + "_cuvid"; + AVCodec *vcodec = avcodec_find_decoder_by_name(cuvid_dec_name.c_str()); + if (!(avctx = avcodec_alloc_context3(vcodec))) return (bool)AVERROR(ENOMEM); // 得到视频流对象 @@ -119,16 +112,12 @@ bool FFNvDecoder::init(const string& path) // 设置解码器管理器的像素格式回调函数 avctx->get_format = get_hw_format; - // 初始化硬件解码器 - AVBufferRef *hw_device_ctx = nullptr; - if (av_hwdevice_ctx_create(&hw_device_ctx, hw_device_type, nullptr, nullptr, 0) < 0) { - cout << "Failed to create specified HW device."; - return false; - } - avctx->hw_device_ctx = av_buffer_ref(hw_device_ctx); + hw_pix_fmt = AV_PIX_FMT_CUDA; // 打开解码器流 - if (avcodec_open2(avctx, decoder, nullptr) < 0) { + AVDictionary *op = nullptr; + av_dict_set( &op, "gpu", gpuid, 0 ); + if (avcodec_open2(avctx, vcodec, &op) < 0) { cout << "Failed to open codec for stream" << stream_index; return false; } @@ -148,6 +137,13 @@ void FFNvDecoder::start(){ return (void*)0; } ,this); +} + +void FFNvDecoder::decode_thread() +{ + AVPacket* pkt ; + pkt = av_packet_alloc(); + av_init_packet( pkt ); pthread_create(&m_post_decode_thread,0, [](void* arg) @@ -157,13 +153,6 @@ void FFNvDecoder::start(){ return (void*)0; } ,this); -} - -void FFNvDecoder::decode_thread() -{ - AVPacket* pkt ; - pkt = av_packet_alloc(); - av_init_packet( pkt ); while (m_bRunning) { @@ -210,7 +199,7 @@ void FFNvDecoder::decode_thread() result = avcodec_send_packet(avctx, pkt); if (result < 0) { - cout << "Failed to send pkt" << result << endl; + cout << "Failed to send pkt:" << result << endl; continue; } @@ -222,24 +211,41 @@ void FFNvDecoder::decode_thread() } mFrameQueue.addTail(); - - // if (gpuFrame->format == hw_pix_fmt) - // { - // /* retrieve data from GPU to CPU */ - // if (av_hwframe_transfer_data(pong_frame, gpuFrame, 0) < 0) - // { - // cout << "Failed to transfer the data to system memory"; - // return; - // } - // } } av_packet_unref(pkt); } m_bRunning = false; + + if (m_post_decode_thread != 0) + { + pthread_join(m_post_decode_thread,0); + } + + decode_finished(); + cout << "decode thread exited." << endl; } +void FFNvDecoder::decode_finished() +{ + if (avctx) + { + if (avctx->hw_device_ctx) + { + av_buffer_unref(&avctx->hw_device_ctx); + } + avcodec_free_context(&avctx); + } + + if (fmt_ctx) + { + avformat_close_input(&fmt_ctx); + } + + m_bFinished = true; +} + void FFNvDecoder::post_decode_thread() { while (m_bRunning) @@ -262,21 +268,8 @@ void FFNvDecoder::post_decode_thread() void FFNvDecoder::close() { m_bRunning=false; - pthread_join(m_decode_thread,0); - pthread_join(m_post_decode_thread,0); - - if (avctx) - { - if (avctx->hw_device_ctx) - { - av_buffer_unref(&avctx->hw_device_ctx); - } - avcodec_free_context(&avctx); - } - - if (fmt_ctx) - { - avformat_close_input(&fmt_ctx); + if(m_decode_thread != 0){ + pthread_join(m_decode_thread,0); } } @@ -298,6 +291,11 @@ bool FFNvDecoder::isRunning() return m_bRunning; } +bool FFNvDecoder::isFinished() +{ + return m_bFinished; +} + bool FFNvDecoder::getResolution( int &width, int &height ) { if (avctx != nullptr) diff --git a/src/FFNvDecoder.h b/src/FFNvDecoder.h index a225634..6e39b93 100644 --- a/src/FFNvDecoder.h +++ b/src/FFNvDecoder.h @@ -20,7 +20,7 @@ using namespace std; * 接口:DXDECODER_CALLBACK * 功能:解码数据回调接口 * 参数:const dx_void * userPtr 用户自定义数据 -* AVFrame * gpuFrame 解码结果帧数据 +* AVFrame * gpuFrame 解码结果帧数据,在设置的对应的gpu上,要十分注意这一点,尤其是多线程情况 * 返回:无 * 备注:当解码库数据源为实时流时(RTSP/GB28181),本接 * 口内不可进行阻塞/耗时操作。当解码库数据源为 @@ -29,17 +29,26 @@ using namespace std; **************************************************/ typedef void(*POST_DECODE_CALLBACK)(const void * userPtr, AVFrame * gpuFrame); +struct FFDecConfig +{ + string uri; + POST_DECODE_CALLBACK post_decoded_cbk; + string gpuid; + bool force_tcp{true}; +}; + class FFNvDecoder{ public: FFNvDecoder(); ~FFNvDecoder(); - bool init(const string& path); + bool init(FFDecConfig& cfg); void close(); void start(); void pause(); void resume(); bool isRunning(); + bool isFinished(); bool getResolution( int &width, int &height ); void setName(string nm); @@ -51,10 +60,13 @@ public: private: void decode_thread(); void post_decode_thread(); + bool init(const char* uri, const char* gpuid, bool force_tcp); + void decode_finished(); public: POST_DECODE_CALLBACK post_decoded_cbk; const void * m_userPtr; + FFDecConfig m_cfg; private: AVStream* stream; @@ -67,6 +79,7 @@ private: pthread_t m_post_decode_thread; bool m_bRunning; + bool m_bFinished; string name; bool m_bPause; diff --git a/src/FFNvDecoderManager.cpp b/src/FFNvDecoderManager.cpp index e146728..c7c2057 100644 --- a/src/FFNvDecoderManager.cpp +++ b/src/FFNvDecoderManager.cpp @@ -3,8 +3,12 @@ using namespace std; -FFNvDecoder* FFNvDecoderManager::createDecoder(const char * uri, POST_DECODE_CALLBACK post_decoded_cbk, string name){ - int num = decoderMap.count(name); + +FFNvDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig& config){ + + closeAllFinishedDecoder(); + + int num = decoderMap.count(config.name); if (num > 0) { cout << "已存在name所标记的解码器" << endl; @@ -17,12 +21,12 @@ FFNvDecoder* FFNvDecoderManager::createDecoder(const char * uri, POST_DECODE_CAL return nullptr; } - bool bRet= dec->init(uri); + bool bRet= dec->init(config.cfg); if (bRet) { - dec->setName(name) ; - dec->post_decoded_cbk = post_decoded_cbk; - decoderMap[name] = dec; + dec->setName(config.name) ; + dec->post_decoded_cbk = config.cfg.post_decoded_cbk; + decoderMap[config.name] = dec; return dec; } @@ -126,11 +130,26 @@ void FFNvDecoderManager::closeAllDecoder() { for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){ iter->second->close(); + delete iter->second; + } + decoderMap.clear(); +} + +void FFNvDecoderManager::closeAllFinishedDecoder() +{ + for(auto iter = decoderMap.begin(); iter != decoderMap.end(); iter++){ + if (iter->second->isFinished()) + { + delete iter->second; + decoderMap.erase(iter); + } } } int FFNvDecoderManager::count() { + closeAllFinishedDecoder(); + return decoderMap.size(); } @@ -172,10 +191,27 @@ bool FFNvDecoderManager::resumeDecoder(string name) return false; } -bool FFNvDecoderManager::isSurport(const char* uri) +bool FFNvDecoderManager::isSurport(FFDecConfig& cfg) { FFNvDecoder dec; - bool bRet = dec.init(uri); + bool bRet = dec.init(cfg); dec.close(); return bRet; +} + +bool FFNvDecoderManager::isRunning(string name){ + if (name.empty()) + { + cout << "name 为空!"<< endl; + return false; + } + + auto dec = decoderMap.find(name); + if (dec != decoderMap.end()) + { + return dec->second->isRunning(); + } + + cout << "没有找到name为" << name << "的解码器!" << endl; + return false; } \ No newline at end of file diff --git a/src/FFNvDecoderManager.h b/src/FFNvDecoderManager.h index 6ae1efb..b609339 100644 --- a/src/FFNvDecoderManager.h +++ b/src/FFNvDecoderManager.h @@ -5,6 +5,12 @@ using namespace std; +struct MgrDecConfig +{ + FFDecConfig cfg; + string name{""}; +}; + class FFNvDecoderManager{ public: static FFNvDecoderManager* getInstance(){ @@ -20,7 +26,7 @@ public: closeAllDecoder(); } - FFNvDecoder* createDecoder(const char * uri, POST_DECODE_CALLBACK post_decoded_cbk, string name = ""); + FFNvDecoder* createDecoder(MgrDecConfig& config); void setUserPtr(string name, const void * userPtr); FFNvDecoder* getDecoderByName(const string name); @@ -31,11 +37,16 @@ public: bool closeDecoderByName(string name); void closeAllDecoder(); + void closeAllFinishedDecoder(); + + bool removeDecoderByName(string name); bool pauseDecoder(string name); bool resumeDecoder(string name); - bool isSurport(const char* uri); + bool isSurport(FFDecConfig& cfg); + + bool isRunning(string name); int count(); diff --git a/src/NV12ToRGB.cu b/src/NV12ToRGB.cu index aca7e6f..c54de2c 100644 --- a/src/NV12ToRGB.cu +++ b/src/NV12ToRGB.cu @@ -301,26 +301,6 @@ namespace cuda_common fprintf(stderr, "cudaMemcpyToSymbol failed: %s\n", cudaGetErrorString(cudaStatus)); } - //showHueCSC(); - - return cudaStatus; - } - - cudaError_t showHueCSC3() - { - /* - cudaError_t cudaStatus; - - float data[9]; - cudaStatus = cudaMemcpyFromSymbol(data, constHueColorSpaceMat2, sizeof(data)); - printf("hueCSC "); - for (int i = 0; i < 9; i++) - { - printf("%f ,", data[i]); - } - printf("\n"); -*/ - cudaError_t cudaStatus; return cudaStatus; } diff --git a/src/NvJpegEncoder.cpp b/src/NvJpegEncoder.cpp index 2db0bff..8cee91f 100644 --- a/src/NvJpegEncoder.cpp +++ b/src/NvJpegEncoder.cpp @@ -1,82 +1,90 @@ #include "NvJpegEncoder.h" -#include - #include #include #include +#define CHECK_NVJPEG(S) do {nvjpegStatus_t status; \ + status = S; \ + if (status != NVJPEG_STATUS_SUCCESS ) std::cout << __LINE__ <<" CHECK_NVJPEG - status = " << status << std::endl; \ + } while (false) + int saveJpeg(const char * filepath, unsigned char* d_srcBGR, int width, int height) { - nvjpegHandle_t nvjpeg_handle; - nvjpegEncoderState_t encoder_state; - nvjpegEncoderParams_t encoder_params; - - cudaEvent_t ev_start, ev_end; - cudaEventCreate(&ev_start); - cudaEventCreate(&ev_end); - - - nvjpegImage_t input; - nvjpegInputFormat_t input_format = NVJPEG_INPUT_BGRI; - int image_width = width; - int image_height = height; - - // int channel_size = image_width * image_height; - // for (int i = 0; i < 3; i++) - // { - // input.pitch[i] = image_width; - // (cudaMalloc((void**)&(input.channel[i]), channel_size)); - // (cudaMemset(input.channel[i], 50 * 40 * i, channel_size)); - // } + nvjpegHandle_t nvjpeg_handle; + nvjpegEncoderState_t encoder_state; + nvjpegEncoderParams_t encoder_params; + + cudaEvent_t ev_start, ev_end; + cudaEventCreate(&ev_start); + cudaEventCreate(&ev_end); + + nvjpegImage_t input; + nvjpegInputFormat_t input_format = NVJPEG_INPUT_BGRI; + int image_width = width; + int image_height = height; + + // int channel_size = image_width * image_height; + // for (int i = 0; i < 3; i++) + // { + // input.pitch[i] = image_width; + // (cudaMalloc((void**)&(input.channel[i]), channel_size)); + // (cudaMemset(input.channel[i], 50 * 40 * i, channel_size)); + // } input.channel[0] = d_srcBGR; input.pitch[0] = image_width * 3; - nvjpegBackend_t backend = NVJPEG_BACKEND_DEFAULT; - - nvjpegCreate(backend, nullptr, &nvjpeg_handle); - - nvjpegEncoderParamsCreate(nvjpeg_handle, &encoder_params, NULL); - nvjpegEncoderStateCreate(nvjpeg_handle, &encoder_state, NULL); - - // set params - nvjpegEncoderParamsSetEncoding(encoder_params, nvjpegJpegEncoding_t::NVJPEG_ENCODING_PROGRESSIVE_DCT_HUFFMAN, NULL); - nvjpegEncoderParamsSetOptimizedHuffman(encoder_params, 1, NULL); - nvjpegEncoderParamsSetQuality(encoder_params, 70, NULL); - nvjpegEncoderParamsSetSamplingFactors(encoder_params, nvjpegChromaSubsampling_t::NVJPEG_CSS_420, NULL); - - cudaEventRecord(ev_start); - nvjpegEncodeImage(nvjpeg_handle, encoder_state, encoder_params, &input, input_format, image_width, image_height, NULL); - cudaEventRecord(ev_end); - - std::vector obuffer; - size_t length; - nvjpegEncodeRetrieveBitstream( - nvjpeg_handle, - encoder_state, - NULL, - &length, - NULL); - - obuffer.resize(length); - nvjpegEncodeRetrieveBitstream( - nvjpeg_handle, - encoder_state, - obuffer.data(), - &length, - NULL); - - std::ofstream outputFile(filepath, std::ios::out | std::ios::binary); - outputFile.write(reinterpret_cast(obuffer.data()), static_cast(length)); - - cudaEventSynchronize(ev_end); - - float ms; - cudaEventElapsedTime(&ms, ev_start, ev_end); - std::cout << "time spend " << ms << " ms" << std::endl; - - return 0; + nvjpegBackend_t backend = NVJPEG_BACKEND_DEFAULT; + + CHECK_NVJPEG(nvjpegCreate(backend, nullptr, &nvjpeg_handle)); + + CHECK_NVJPEG(nvjpegEncoderParamsCreate(nvjpeg_handle, &encoder_params, NULL)); + CHECK_NVJPEG(nvjpegEncoderStateCreate(nvjpeg_handle, &encoder_state, NULL)); + + // set params + CHECK_NVJPEG(nvjpegEncoderParamsSetEncoding(encoder_params, nvjpegJpegEncoding_t::NVJPEG_ENCODING_PROGRESSIVE_DCT_HUFFMAN, NULL)); + CHECK_NVJPEG(nvjpegEncoderParamsSetOptimizedHuffman(encoder_params, 1, NULL)); + CHECK_NVJPEG(nvjpegEncoderParamsSetQuality(encoder_params, 70, NULL)); + CHECK_NVJPEG(nvjpegEncoderParamsSetSamplingFactors(encoder_params, nvjpegChromaSubsampling_t::NVJPEG_CSS_420, NULL)); + + cudaEventRecord(ev_start); + CHECK_NVJPEG(nvjpegEncodeImage(nvjpeg_handle, encoder_state, encoder_params, &input, input_format, image_width, image_height, NULL)); + cudaEventRecord(ev_end); + + std::vector obuffer; + size_t length; + CHECK_NVJPEG(nvjpegEncodeRetrieveBitstream( + nvjpeg_handle, + encoder_state, + NULL, + &length, + NULL)); + + obuffer.resize(length); + CHECK_NVJPEG(nvjpegEncodeRetrieveBitstream( + nvjpeg_handle, + encoder_state, + obuffer.data(), + &length, + NULL)); + + cudaEventSynchronize(ev_end); + + // 用完销毁,避免显存泄露 + nvjpegEncoderParamsDestroy(encoder_params); + nvjpegEncoderStateDestroy(encoder_state); + nvjpegDestroy(nvjpeg_handle); + + float ms; + cudaEventElapsedTime(&ms, ev_start, ev_end); + std::cout << "time spend " << ms << " ms" << std::endl; + + std::ofstream outputFile(filepath, std::ios::out | std::ios::binary); + outputFile.write(reinterpret_cast(obuffer.data()), static_cast(length)); + outputFile.close(); + + return 0; } \ No newline at end of file diff --git a/src/NvJpegEncoder.h b/src/NvJpegEncoder.h index fd5fadd..8d63d97 100644 --- a/src/NvJpegEncoder.h +++ b/src/NvJpegEncoder.h @@ -1,3 +1,3 @@ - +#include int saveJpeg(const char * filepath, unsigned char* d_srcBGR, int width, int height); \ No newline at end of file diff --git a/src/cuda_kernels.h b/src/cuda_kernels.h index fcef461..966a1af 100644 --- a/src/cuda_kernels.h +++ b/src/cuda_kernels.h @@ -19,7 +19,6 @@ typedef enum namespace cuda_common { cudaError_t setColorSpace2(e_ColorSpace CSC, float hue); - cudaError_t showHueCSC3(); cudaError_t NV12ToRGBnot(CUdeviceptr d_srcNV12, size_t nSourcePitch, unsigned char* d_dstRGB, int width, int height); cudaError_t CUDAToBGR(CUdeviceptr dataY, CUdeviceptr dataUV, size_t pitchY, size_t pitchUV, unsigned char* d_dstRGB, int width, int height); diff --git a/src/main.cpp b/src/main.cpp index 29fda28..a36d59a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,54 +7,103 @@ unsigned char *pHwRgb = nullptr; - +/** + * 注意: gpuFrame 在解码器设置的显卡上,后续操作要十分注意这一点,尤其是多线程情况 + * */ void postDecoded(const void * userPtr, AVFrame * gpuFrame){ FFNvDecoder* decoder = (FFNvDecoder*)userPtr; if (decoder!= nullptr) { - cout << decoder->getName() << endl; - const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format); - cout << "pixfmt: " << gpu_pixfmt << endl; + cout << "decode name: " << decoder->getName() << endl; + // const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format); + // cout << "pixfmt: " << gpu_pixfmt << endl; cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl; - cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl; + // cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl; if (gpuFrame->format == AV_PIX_FMT_CUDA) - { - cudaError_t cudaStatus; - if(pHwRgb == nullptr){ - cudaStatus = cudaMalloc((void **)&pHwRgb, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char)); - } - cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb, gpuFrame->width, gpuFrame->height); - cudaDeviceSynchronize(); - if (cudaStatus != cudaSuccess) { - cout << "CUDAToBGR failed !!!" << endl; - return; - } - saveJpeg("/home/cmhu/FFNvDecoder/a.jpg", pHwRgb, gpuFrame->width, gpuFrame->height); // 验证 CUDAToRGB + { + cout << "gpuid = " << atoi(decoder->m_cfg.gpuid.c_str()) << endl; + // cudaSetDevice(atoi(decoder->m_cfg.gpuid.c_str())); + // cudaError_t cudaStatus; + // if(pHwRgb == nullptr){ + // cuda_common::setColorSpace2( ITU709, 0 ); + // cudaStatus = cudaMalloc((void **)&pHwRgb, 3 * gpuFrame->width * gpuFrame->height * sizeof(unsigned char)); + // } + // cudaStatus = cuda_common::CUDAToBGR((CUdeviceptr)gpuFrame->data[0],(CUdeviceptr)gpuFrame->data[1], gpuFrame->linesize[0], gpuFrame->linesize[1], pHwRgb, gpuFrame->width, gpuFrame->height); + // cudaDeviceSynchronize(); + // if (cudaStatus != cudaSuccess) { + // cout << "CUDAToBGR failed !!!" << endl; + // return; + // } + + // string path = "/home/cmhu/FFNvDecoder/" + decoder->m_cfg.gpuid + ".jpg"; + // saveJpeg(path.c_str(), pHwRgb, gpuFrame->width, gpuFrame->height); // 验证 CUDAToRGB } } } -int main(){ +void createDecode(int index){ + FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); + MgrDecConfig config; + config.name = "dec" + to_string(index); + config.cfg.uri = "rtsp://176.10.0.4:8554/stream"; + config.cfg.post_decoded_cbk = postDecoded; + config.cfg.force_tcp = true; + config.cfg.gpuid = "1"; + FFNvDecoder* decoder = pDecManager->createDecoder(config); + if (!decoder) + { + return ; + } + pDecManager->setUserPtr(config.name, decoder); + pDecManager->startDecodeByName(config.name); +} - cuda_common::setColorSpace2( ITU709, 0 ); +int main(){ FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); - // FFNvDecoder* decoder = pDecManager->createDecoder("rtmp://192.168.10.56:1935/objecteye/1",postDecoded,"dec1"); - // if (!decoder) + + // for (size_t i = 0; i < 20; i++) // { - // return 1; + // createDecode(i); // } - // pDecManager->setUserPtr("dec1", decoder); - // pDecManager->startDecodeByName("dec1"); - FFNvDecoder* dec2 = pDecManager->createDecoder("/home/cmhu/data/duan1.avi",postDecoded,"dec2"); + MgrDecConfig config; + config.name = "dec2"; + config.cfg.uri = "/home/cmhu/data/test.mp4"; + config.cfg.post_decoded_cbk = postDecoded; + config.cfg.force_tcp = true; + config.cfg.gpuid = "2"; + FFNvDecoder* dec2 = pDecManager->createDecoder(config); if (!dec2) { return 1; } - pDecManager->setUserPtr("dec2", dec2); - pDecManager->startDecodeByName("dec2"); + pDecManager->setUserPtr(config.name, dec2); + pDecManager->startDecodeByName(config.name); + + + // config.name = "dec0"; + // config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1"; + // config.cfg.gpuid = "0"; + // FFNvDecoder* dec0 = pDecManager->createDecoder(config); + // if (!dec0) + // { + // return 1; + // } + // pDecManager->setUserPtr(config.name, dec0); + // pDecManager->startDecodeByName(config.name); + + // config.name = "dec01"; + // config.cfg.uri = "rtmp://192.168.10.56:1935/objecteye/1"; + // config.cfg.gpuid = "0"; + // FFNvDecoder* dec01 = pDecManager->createDecoder(config); + // if (!dec01) + // { + // return 1; + // } + // pDecManager->setUserPtr(config.name, dec01); + // pDecManager->startDecodeByName(config.name); // while (getchar() != 'q');