166 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| /**
 | ||
|  * 视频流解码引擎
 | ||
|  * */
 | ||
| 
 | ||
| #include "VideoDecodeEngine.h"
 | ||
| 
 | ||
| using namespace std;
 | ||
| using namespace cv;
 | ||
| using namespace ai_matrix;
 | ||
| 
 | ||
| VideoDecodeEngine::VideoDecodeEngine() {}
 | ||
| 
 | ||
| VideoDecodeEngine::~VideoDecodeEngine() {}
 | ||
| 
 | ||
| APP_ERROR VideoDecodeEngine::Init()
 | ||
| {
 | ||
|     bUseEngine_ = true;
 | ||
|     dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_); // 获取摄像机参数
 | ||
| 
 | ||
|     strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
 | ||
|     if (MyYaml::GetIns()->GetStringValue("gc_data_source") != "camera" || !dataSourceConfig_.bUse)
 | ||
|     {
 | ||
|         bUseEngine_ = false;
 | ||
|         LogWarn << "engineId_:" << engineId_ << " not use engine";
 | ||
|         return APP_ERR_OK;
 | ||
|     }
 | ||
| 
 | ||
|     LogInfo << "VideoDecodeEngine Init ok";
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| APP_ERROR VideoDecodeEngine::DeInit()
 | ||
| {
 | ||
|     if (!bUseEngine_)
 | ||
|     {
 | ||
|         LogWarn << "engineId_:" << engineId_ << " not use engine";
 | ||
|         return APP_ERR_OK;
 | ||
|     }
 | ||
| 
 | ||
|     if (hard_h264_ffmpeg_decoder_ != nullptr)
 | ||
|     {
 | ||
|         hard_h264_ffmpeg_decoder_->HardH264FFmpegDecoderDeInit();
 | ||
|         delete hard_h264_ffmpeg_decoder_;
 | ||
|         hard_h264_ffmpeg_decoder_ = nullptr;
 | ||
|     }
 | ||
|     LogInfo << "VideoDecodeEngine DeInit ok";
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| APP_ERROR VideoDecodeEngine::Process()
 | ||
| {
 | ||
|     if (!bUseEngine_)
 | ||
|     {
 | ||
|         LogWarn << "engineId_:" << engineId_ << " not use engine";
 | ||
|         return APP_ERR_OK;
 | ||
|     }
 | ||
| 
 | ||
|     int iRet = APP_ERR_OK;
 | ||
| 	int iSkipCount = 1;
 | ||
|     int iNoCameraDataCnt = 0;
 | ||
|     while (!isStop_)
 | ||
|     {
 | ||
|         //从上一引擎接收图像数据
 | ||
|         std::shared_ptr<void> pVoidData0 = nullptr;
 | ||
|         inputQueMap_[strPort0_]->pop(pVoidData0);
 | ||
|         if (nullptr == pVoidData0)
 | ||
|         {
 | ||
|             usleep(10*1000); //10ms
 | ||
| 
 | ||
|             iNoCameraDataCnt++;
 | ||
|             if (iNoCameraDataCnt >= 1000) //10秒内收不到,认为相机断开
 | ||
|             {
 | ||
|                 LogError << "engineId:" << engineId_ << " 超过10秒获取到摄像头数据,疑似摄像头断开。计数:" << iNoCameraDataCnt;
 | ||
|                 iNoCameraDataCnt = 0;
 | ||
|                 //camera异常时,构造空的解码数据push,确保一直有数据流转到后面Engine
 | ||
|                 std::shared_ptr<ProcessData> pProcessData = std::make_shared<ProcessData>();
 | ||
|                 pProcessData->iDataSource = engineId_;
 | ||
|                 pProcessData->i64TimeStamp = MyUtils::getins()->GetCurrentTimeMillis();
 | ||
|                 pProcessData->iSize = 0;
 | ||
|                 pProcessData->pData = nullptr;
 | ||
|                 iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pProcessData));
 | ||
|             }
 | ||
| 
 | ||
|             continue;
 | ||
|         }
 | ||
| 
 | ||
|         iNoCameraDataCnt = 0;
 | ||
|         std::shared_ptr<ProcessData> pProcessData = std::static_pointer_cast<ProcessData>(pVoidData0);
 | ||
| 
 | ||
|         //创建解码类
 | ||
|         if (hard_h264_ffmpeg_decoder_ == nullptr)
 | ||
|         {
 | ||
|             hard_h264_ffmpeg_decoder_ = new HardH264FFmpegDecode;
 | ||
|             int iRet = hard_h264_ffmpeg_decoder_->HardH264FFmpegDecoderInit(pProcessData->iWidth, pProcessData->iHeight, pProcessData->iRate);
 | ||
|             if (iRet != 0)
 | ||
|             {
 | ||
|                 LogError << "engineId:" << engineId_ << " HardH264FFmpegDecoderInit Failed";
 | ||
|                 if (hard_h264_ffmpeg_decoder_ != nullptr)
 | ||
|                 {
 | ||
|                     delete hard_h264_ffmpeg_decoder_;
 | ||
|                     hard_h264_ffmpeg_decoder_ = nullptr;
 | ||
|                 }
 | ||
|                 continue;
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         //构造YUV420M数据
 | ||
|         unsigned int pYUV420MBuffer_Size = pProcessData->iWidth * pProcessData->iHeight * 3 / 2;
 | ||
|         void *pYUV420MBuffer = nullptr;
 | ||
|         pYUV420MBuffer = new uint8_t[pYUV420MBuffer_Size];
 | ||
|         std::shared_ptr<void> pYUVData;
 | ||
|         pYUVData.reset(pYUV420MBuffer, [](void *data){if(data) {delete[] data; data = nullptr;}}); //智能指针管理内存
 | ||
| 
 | ||
| 		hard_h264_ffmpeg_decoder_->pPacket_->data = static_cast<uint8_t *>(pProcessData->pData.get());	//这里填入一个指向完整H264数据帧的指针  
 | ||
| 		hard_h264_ffmpeg_decoder_->pPacket_->size = pProcessData->iSize;	//这个填入H264数据帧的大小
 | ||
| 
 | ||
|         // H264硬件解码
 | ||
|         // int iDecodeRet= hard_h264_ffmpeg_decoder_->HardH264FFmpegDecoderV2(hard_h264_ffmpeg_decoder_->pCodecCtx_, hard_h264_ffmpeg_decoder_->pFrame_,
 | ||
|         //                                                        hard_h264_ffmpeg_decoder_->pPacket_, pYUV420MBuffer, &pYUV420MBuffer_Size);
 | ||
| 
 | ||
|         int iDecodeRet = hard_h264_ffmpeg_decoder_->HardH264FFmpegDecoderV2(hard_h264_ffmpeg_decoder_->pCodecCtx_,
 | ||
|                                                                             hard_h264_ffmpeg_decoder_->pSwsContext_,
 | ||
|                                                                             hard_h264_ffmpeg_decoder_->pSrcFrame_,
 | ||
|                                                                             hard_h264_ffmpeg_decoder_->pDstFrame_,
 | ||
|                                                                             hard_h264_ffmpeg_decoder_->pPacket_,
 | ||
|                                                                             pYUV420MBuffer,
 | ||
|                                                                             &pYUV420MBuffer_Size);
 | ||
|         if (iDecodeRet > 0)
 | ||
|         {
 | ||
|             if (iSkipCount++ % dataSourceConfig_.iSkipInterval != 0)
 | ||
|             {
 | ||
|                 continue;
 | ||
|             }
 | ||
|             iSkipCount = 1;
 | ||
| 
 | ||
|             //硬解码YUV转BGR
 | ||
|             cv::Mat matYUV(pProcessData->iHeight * 3 / 2, pProcessData->iWidth, CV_8UC1);
 | ||
|             memcpy(matYUV.data, static_cast<uint8_t *>(pYUVData.get()), pYUV420MBuffer_Size);
 | ||
| 
 | ||
|             cv::Mat matBGR(pProcessData->iHeight, pProcessData->iWidth, CV_8UC3);
 | ||
|             cv::cvtColor(matYUV, matBGR, cv::COLOR_YUV2BGR_I420);
 | ||
| 
 | ||
|             cv::resize(matBGR, matBGR, cv::Size(IMAGE_WIDTH, IMAGE_HEIGHT));
 | ||
|             unsigned int iResizeSize = IMAGE_WIDTH * IMAGE_HEIGHT * 3;
 | ||
|             void *pResizeBGRBuffer = nullptr;
 | ||
|             pResizeBGRBuffer = new uint8_t[iResizeSize];
 | ||
|             memcpy(pResizeBGRBuffer, matBGR.data, iResizeSize);
 | ||
|             pProcessData->pData.reset(pResizeBGRBuffer, [](void *data) {if(data) {delete[] data; data = nullptr;} });
 | ||
|             pProcessData->iSize = iResizeSize;
 | ||
|             pProcessData->iWidth = IMAGE_WIDTH;
 | ||
|             pProcessData->iHeight = IMAGE_HEIGHT;
 | ||
| 
 | ||
|             iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pProcessData));
 | ||
|             if (iRet != APP_ERR_OK)
 | ||
|             {
 | ||
|                 LogError << "push the after hard h264 decode yuv420m frame data failed...";
 | ||
|             }
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             LogError << "engineId:" << engineId_ << " HardH264FFmpegDecoderV2 failed...iDecodeRet:" << iDecodeRet;
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 |