#include #include "DxDecoderWrap.h" #include "ColorSpace.h" #include "sfx_depend_inc.h" #include #ifndef SFX_STD_LOG_DONE #define SFX_STD_LOG_DONE "done" #endif static void CUDADecoder_Callback(const void * userPtr, void * buf, unsigned int size, int width, int height, unsigned long long timestamp){ DxDecoderWrap* _this = (DxDecoderWrap*)userPtr; if(nullptr != _this){ _this->DxCUDADecoderCallback(buf, size, width, height, timestamp); } } static int DecoderLog_Callback( const void * userPtr, DxLogLevel level, const char * log, unsigned int logLen ){ DxDecoderWrap* _this = (DxDecoderWrap*)userPtr; if(nullptr != _this){ _this->DxDecoderLogCallback(level, log, logLen); } } static long get_cur_time_ms() { chrono::time_point tpMicro = chrono::time_point_cast(chrono::system_clock::now()); return tpMicro.time_since_epoch().count(); } DxDecoderWrap::DxDecoderWrap( ) { m_pDec = nullptr; m_skip = 0; return; } int frame_nb = 0; DxDecoderWrap::~DxDecoderWrap() { DxCloseDecoder(); std::cout << "总帧数" << frame_nb << std::endl; return; } bool DxDecoderWrap::isStream(string sVideoFileName) { string target = "file://"; int pos = sVideoFileName.find(target); if (pos == 0) { int n = target.size(); sVideoFileName = sVideoFileName.erase(pos, n); } pos = sVideoFileName.find_first_of('?'); if (pos != string::npos) { sVideoFileName = sVideoFileName.substr(0, pos); } bool bReal = false; FILE* fp=fopen(sVideoFileName.c_str(),"rb"); if(fp!=nullptr) { bReal = false; fclose(fp); } else { bReal = true; } return bReal; } int DxDecoderWrap::DxOpenDecoder(const DxConfig& cfg) { //判断是否为实时流 m_bReal = isStream(cfg.uri); m_nums = 0; m_bPause = false; m_pDec = new SfxDecoder(); if ( nullptr == m_pDec ) { return -1; } DxDecoderConfig m_cfg; m_cfg.userPtr = this; m_cfg.escbk = CUDADecoder_Callback; m_cfg.logcbk = DecoderLog_Callback; m_cfg.devId = cfg.devId; m_cfg.uri = cfg.uri; m_cfg.dec_name = cfg.name; m_skip = cfg.skip_frame; m_name = cfg.name; m_devId = cfg.devId; bool bRet= m_pDec->OpenDecoder(m_cfg); if (bRet) { m_bRun = true; LOG_INFO("[{}][{}]- 解码器初始化成功", m_name.c_str(), m_cfg.uri); return 0; } // 创建失败,关闭解码器 m_pDec->CloseDecoder(); delete m_pDec; m_pDec = nullptr; LOG_ERROR("[{}][{}]- 解码器初始化失败!", m_name.c_str(), m_cfg.uri); return -1; } int DxDecoderWrap::DxCloseDecoder() { if (m_pDec) { m_pDec->CloseDecoder(); delete m_pDec; m_pDec = nullptr; } m_queue_frames_mutex.lock(); while (m_queue_frames.size() > 0) { DxGPUFrame decodedFrame = m_queue_frames.front(); if (decodedFrame.frame) { cudaFree(decodedFrame.frame); decodedFrame.frame = nullptr; } m_queue_frames.pop(); } m_queue_frames_mutex.unlock(); } bool DxDecoderWrap::DxDecoderIsFinished() { if(m_pDec) { return m_pDec->isFinished(); } return true; } int DxDecoderWrap::DxGetResolution( int &width, int &height ) { width = m_width; height = m_height; } bool DxDecoderWrap::DxFrameIsEmpty() { m_queue_frames_mutex.lock(); int count = m_queue_frames.size(); m_queue_frames_mutex.unlock(); return 0 == count; } int DxDecoderWrap::DxLockFrame(DxGPUFrame& frame) { std::lock_guard l(m_queue_frames_mutex); if(m_queue_frames.size() <= 0) { return -1; } frame = m_queue_frames.front(); m_queue_frames.pop(); return 0; } DxGPUFrame DxDecoderWrap::DxGetFrame() { std::lock_guard l(m_queue_frames_mutex); DxGPUFrame frame; if(m_queue_frames.size() <= 0) { return frame; } frame = m_queue_frames.front(); m_queue_frames.pop(); return frame; } int DxDecoderWrap::PauseDecoder() { m_bPause = true; return 0; } int DxDecoderWrap::ResumeDecoder() { m_bPause = false; return 0; } bool DxDecoderWrap::DxDecoderIsRun() const { return m_bRun; } unsigned int DxDecoderWrap::DxGetFrameCount() { if(m_pDec) { return m_pDec->GetFrameCount(); } return 1; } int DxDecoderWrap::DxDecoderLogCallback(DxLogLevel level, const char * log, unsigned int logLen ) { int index = 0; if ( DX_LOG_LEVEL_FATAL == level ) { return 0; } if (DX_LOG_LEVEL_IMPORTANT == level) { if (0 == memcmp( log, SFX_STD_LOG_DONE, strlen(SFX_STD_LOG_DONE) + 1)) { m_bRun = false; return 0; } if (0 == memcmp( log, "progress ", strlen( "progress ") ) ) { //printf("%s\n", log); //打印进度 格式:progress 100 } } if ( DX_LOG_LEVEL_CLEANUP == level ) { LOG_INFO( "{}", log ); m_bRun = false; } return 0; } void DxDecoderWrap::DxCUDADecoderCallback( void * buf, unsigned int size, int width, int height, unsigned long long timestamp ) { if ( 0 == size ) { m_width = width; m_height = height; return; } m_nums++; while ( m_bRun ) { if ( m_bPause ) { if ( m_bReal ) { return; } std::this_thread::sleep_for(std::chrono::milliseconds(50)); continue; } break; } if ( !m_bRun ) { return; } if ( m_skip > 0 ) { if ( m_nums % m_skip ) { return; } } while(m_bRun) { m_queue_frames_mutex.lock(); if(m_queue_frames.size() < 3) { // 入队 cudaSetDevice(m_devId); size_t rgbSize = 3 * m_width * m_height * sizeof(unsigned char); unsigned char *pHwData = nullptr; cudaError_t cudaStatus = cudaMalloc((void **)&pHwData, rgbSize); if (cudaStatus != cudaSuccess) { LOG_ERROR("[{}]- cudaMalloc failed !!!", m_name.c_str()); return ; } Nv12ToColor24((unsigned char*)buf, width, pHwData, 3 * width, width, height, 0); DxGPUFrame frame; frame.width = m_width; frame.height = m_height; frame.size = m_width; frame.frame = pHwData; frame.timestamp = timestamp; frame.dec_name = m_name; m_queue_frames.push(frame); m_queue_frames_mutex.unlock(); frame_nb++; std::cout << "in queue " << frame_nb << std::endl; break; } else { m_queue_frames_mutex.unlock(); if (m_bReal) { // 实时流不等待,直接弃帧 return; } std::cout << "waiting queue " << frame_nb << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } //int width = m_frames.width; //int height = m_frames.height; //size_t rgbSize = 3 * width * height * sizeof(unsigned char); //unsigned char* pHwData = nullptr; //cudaStatus = cudaMalloc((void**)&pHwData, rgbSize); //if (cudaStatus != cudaSuccess) { // //LOG_ERROR("[{}]- cudaMalloc failed !!!", m_name.c_str()); // return; //} //Nv12ToColor24((unsigned char*)m_frames.frames[m_frames.write].frame, width, pHwData, 3 * width, width, height, 0); //int rgb_size = 3 * width * height; //unsigned char* cpu_data = new unsigned char[rgb_size]; //cudaStatus = cudaMemcpy(cpu_data, pHwData, rgb_size * sizeof(unsigned char), cudaMemcpyDeviceToHost); //cv::Mat img(height, width, CV_8UC3, cpu_data); ////cv::imwrite("test.jpg", img); //cv::imshow("test", img); //cv::waitKey(1); //delete[] cpu_data; //cpu_data = nullptr; //cudaFree(pHwData); }