/** * 视频流解码引擎 * */ #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 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 pProcessData = std::make_shared(); // pProcessData->iDataSource = engineId_; // pProcessData->i64TimeStamp = MyUtils::getins()->GetCurrentTimeMillis(); // pProcessData->iSize = 0; // pProcessData->pData = nullptr; // iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast(pProcessData)); // } continue; } iNoCameraDataCnt = 0; std::shared_ptr pProcessData = std::static_pointer_cast(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 pYUVData; pYUVData.reset(pYUV420MBuffer, [](void *data){if(data) {delete[] data; data = nullptr;}}); //智能指针管理内存 hard_h264_ffmpeg_decoder_->pPacket_->data = static_cast(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(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(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; } } }