QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/StructureApp/AppPipeController.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/StructureApp/FaceExtractElement.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/StructureApp/FaceExtractElement.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/VideoToImageMulth/RtspAnalysManager.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp
@@ -145,7 +145,8 @@ * @param p_this */ void BASICGB28181::FFmpegDecoderJPG::BareFlowDecoderThd(FFmpegDecoderJPG *p_this) { DBG(p_this->m_camIdx << " BareFlowDecoderThd ok ... gpuIdx is " << p_this->m_gpuIdx); DBG(p_this->m_camIdx << " BareFlowDecoderThd ok ... gpuIdx is " << p_this->m_gpuIdx); DBG("p_thisADDR:" << p_this << "p_this->m_running" << p_this->m_running); while (!p_this->m_running) { p_this->m_running = true; QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp
@@ -35,44 +35,49 @@ bool BASICGB28181::VideoCaptureElementWithRtp::startRtpStream(int streamTransType) { //等待下层ffmpeg将rtp包解码成为图片后触发信号,然后触发当前类的submit std::thread waitSignalAndEmit([&](BASICGB28181::VideoCaptureElementWithRtp *p_this) { p_this->m_waitSignal = true; //循环,由成员变量来维护这个线程的运行状态 while (p_this->m_waitSignal) { if(!m_waitSignalrunning) { DBG("std::thread waitSignalAndEmit create New!!"); //等待下层ffmpeg将rtp包解码成为图片后触发信号,然后触发当前类的submit std::thread waitSignalAndEmit([&](BASICGB28181::VideoCaptureElementWithRtp *p_this) { p_this->m_waitSignal = true; p_this->m_waitSignalrunning = true; //循环,由成员变量来维护这个线程的运行状态 while (p_this->m_waitSignal) { //#TODO wait test #ifdef TestCode DBG("waitSignal(\"DecoderImageOK\") begin"); DBG("waitSignal(\"DecoderImageOK\") begin"); #endif //等待信号触发 gSignalLock.waitSignal(p_this->m_chanPubID + "DecoderImageOK"); //等待信号触发 gSignalLock.waitSignal(p_this->m_chanPubID + "DecoderImageOK"); #ifdef TestCode DBG("waitSignal(\"DecoderImageOK\") after"); DBG("waitSignal(\"DecoderImageOK\") after"); #endif /****录像模块代码*****/ p_this->m_picCount++; //几张选一张放入Redis if (p_this->m_picCount % m_nPicsPickOne != 0) { continue; } else { p_this->m_picCount.store(0); } /****录像模块代码*****/ p_this->m_picCount++; //几张选一张放入Redis if (p_this->m_picCount % m_nPicsPickOne != 0) { continue; } else { p_this->m_picCount.store(0); } // 从ffmpeg解码类中获取图片 p_this->m_fFmpegDecoderJPG.getImage().copyTo(p_this->m_image); { cv::Mat copyMat; std::string imageName = p_this->m_fFmpegDecoderJPG.GetImageName(); p_this->m_image.copyTo(copyMat); m_pManager->SaveImageToRedis(p_this->m_chanPubID, imageName, copyMat); } /*********/ p_this->m_fFmpegDecoderJPG.getImage().copyTo(p_this->m_image); { cv::Mat copyMat; std::string imageName = p_this->m_fFmpegDecoderJPG.GetImageName(); p_this->m_image.copyTo(copyMat); m_pManager->SaveImageToRedis(p_this->m_chanPubID, imageName, copyMat); } /*********/ p_this->submit(); } INFO("waitSignalAndEmit is exit..."); }, this); waitSignalAndEmit.detach(); p_this->submit(); } p_this->m_waitSignalrunning = false; INFO("waitSignalAndEmit is exit..."); }, this); waitSignalAndEmit.detach(); } TryCath( //--------------国标设备或则国标下级平台必须支持GB28181-2016---------------------------------------------- @@ -146,9 +151,12 @@ //点播失败 p_this->m_waitSignal = false; p_this->m_running = false; //关闭ffmpeg解码模块 p_this->m_fFmpegDecoderJPG.stopThd(); ERR(p_this->m_chanPubID << " C_RealVideoStart is error lrealhandle is " << lrealhandle); p_this->startRtpStream(p_this->m_streamTransType); } }, this, streamTransType); @@ -196,20 +204,20 @@ void BASICGB28181::VideoCaptureElementWithRtp::threadFunc() { if ((!m_running) || (!m_waitSignal)) { // 根据reopenTime判断是否需要重启 if (reopenTime < 0) { stop(); INFO("grabFrame faild, element stopping"); return; } else { //todo 业务死锁 usleep(reopenTime * 1000); INFO("grabFrame faild, try reopen video: "); startRtpStream(m_streamTransType); return; } } // if ((!m_running) || (!m_waitSignal)) { //// 根据reopenTime判断是否需要重启 // if (reopenTime < 0) { // stop(); // INFO("grabFrame faild, element stopping"); // return; // } else { // //todo 业务死锁 // usleep(reopenTime * 1000); // INFO("grabFrame faild, try reopen video: "); // startRtpStream(m_streamTransType); // return; // } // } fireConnectors(); } QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h
@@ -68,6 +68,7 @@ std::atomic<bool> m_running; std::atomic<bool> m_waitSignal; std::atomic<bool> m_waitSignalrunning; //用来保存录像视频的路径 std::string m_cutPath; QiaoJiaSystem/StructureApp/AppPipeController.cpp
@@ -33,8 +33,7 @@ // recordVideoElement(-1, ""), bRecordVideoEnable(false), m_bSetWH(false) { m_bSetWH(false) { init(); @@ -90,9 +89,7 @@ rightJudgment(ruleMap[KeepRightSdk]), bRecordVideoEnable(RecordVideoEnable), m_sdkRuleMap(ruleMap), m_bSetWH(false) { m_bSetWH(false) { DBG("camId" << camId); init(); initPerimeter(); @@ -229,6 +226,7 @@ "perStaticElement: "<<perStaticElement.getTriggerState()); }*/ } void AppPipeController::init() { unsigned char ip_old[15] = {0}; @@ -261,27 +259,25 @@ m_hiredisTool.listRpop(m_camId,imgKey); if(imgKey.empty()) { ERR("CamId "<<m_camId<<" No ImgKey"); // ERR("CamId "<<m_camId<<" No ImgKey"); return; } cv::Mat imageTemp; m_hiredisTool.getKeyImage(imgKey,imageTemp); if(!m_bSetWH) { INFO("SetWidth:"<<imageTemp.cols<<" Height:"<<imageTemp.rows); appPref.setIntData(m_camId+"width",imageTemp.cols); appPref.setIntData(m_camId+"height",imageTemp.rows); m_bSetWH=true; m_hiredisTool.getKeyImage(imgKey, imageTemp); if (!m_bSetWH) { INFO("SetWidth:" << imageTemp.cols << " Height:" << imageTemp.rows); appPref.setIntData(m_camId + "width", imageTemp.cols); appPref.setIntData(m_camId + "height", imageTemp.rows); m_bSetWH = true; } m_hiredisTool.delKey(imgKey); if(imageTemp.empty()) { ERR("No Image Data In: "<<m_camId<<" ImgKey:"<<imgKey); if (imageTemp.empty()) { ERR("No Image Data In: " << m_camId << " ImgKey:" << imgKey); return; } std::string strNewTime = AppUtil::getTimeUSecString(); std::string strNewTime = AppUtil::getTimeUSecString(); ImageName_s_t imgSt = ImageName_s_t::fromString(imgKey); @@ -289,8 +285,8 @@ if (!faceRpcElement.isBusy()) { //#todo faceRpcElement.setProperty("time", strNewTime); faceRpcElement.setProperty("imgKey",imgKey); INFO("Write To FaceRPC ES time:"<<strNewTime<< " ImgKey: "<<imgKey); faceRpcElement.setProperty("imgKey", imgKey); INFO("Write To FaceRPC ES time:" << strNewTime << " ImgKey: " << imgKey); faceRpcElement.setImage(imageTemp); faceRpcElement.submit(); } @@ -298,8 +294,8 @@ if (!yoloRpcElement.isBusy()) { //#todo yoloRpcElement.setProperty("time", strNewTime); yoloRpcElement.setProperty("imgKey",imgKey); INFO("Write To YoloES time:"<<strNewTime<< " ImgKey: "<<imgKey); yoloRpcElement.setProperty("imgKey", imgKey); INFO("Write To YoloES time:" << strNewTime << " ImgKey: " << imgKey); yoloRpcElement.setImage(imageTemp); yoloRpcElement.submit(); } @@ -385,7 +381,7 @@ imageDrawElement.registerConnector([&] { if (appPref.getIntData("show.image") == 1) { ImageShowElement::showImage(to_string(this->m_index), *imageDrawElement.getImage()); ImageShowElement::showImage(to_string(this->m_index), *imageDrawElement.getImage()); } }); @@ -398,8 +394,7 @@ registerElement(faceRpcElement); registerElement(faceExtractElement); } if(appPref.getIntData("show.image") == 1) { if (appPref.getIntData("show.image") == 1) { imageDrawElement.registerConnector([&] { ImageShowElement::showImage(to_string(this->m_index), *imageDrawElement.getImage()); @@ -409,7 +404,7 @@ registerElement(imageDrawElement); } // registerElement(newRecordVideoElement); // registerElement(newRecordVideoElement); //videoCaptureElement.setOutPutInterval(3); faceExtractElement.setProperty("index", to_string(m_index)); registerElement(yoloRpcElement); @@ -543,14 +538,12 @@ leftJudgment.init(rule.strAreas, rule.strLine); rightJudgment.init(rule.strExAreas, rule.strExLine); yoloRpcElement.registerConnector([&] { if(!leftJudgment.isBusy()) { leftJudgment.setYoloObjects(yoloRpcElement.getLastScoreRects()); leftJudgment.setImage(yoloRpcElement.getImage()); leftJudgment.submit(); if (!leftJudgment.isBusy()) { leftJudgment.setYoloObjects(yoloRpcElement.getLastScoreRects()); leftJudgment.setImage(yoloRpcElement.getImage()); leftJudgment.submit(); } if(!rightJudgment.isBusy()) { if (!rightJudgment.isBusy()) { rightJudgment.setYoloObjects(yoloRpcElement.getLastScoreRects()); rightJudgment.setImage(yoloRpcElement.getImage()); QiaoJiaSystem/StructureApp/FaceExtractElement.cpp
@@ -92,6 +92,20 @@ auto sharedImage = cv::Mat(image.rows, image.cols, CV_8UC3, sharedMemory->data()); image.copyTo(sharedImage); // 上传大图 string strBigImgUrl; if (fdfsClient != nullptr && fdfsClient->fastFds != nullptr) { fdfsClient->rwLock.rdlock(); std::vector<unsigned char> buffer; CvUtil::cvMat2Buffer(image, buffer); fdfsClient->fastFds->uploadFile(buffer, strBigImgUrl, "jpg"); fdfsClient->rwLock.unlock(); } else { strBigImgUrl = ""; ERR("fdfsClient is nullptr ???"); } unsigned long size = faceExtractQueueTmp[i].facesPos.size(); for (int j = 0; j < size; j++) { auto feature = extractServer->faceExtract(image.cols, image.rows, faceExtractQueueTmp[i].facesPos[j], @@ -109,7 +123,6 @@ } features.clear(); features.emplace_back(feature); std::string strImgUrl = "http://"; if (fdfsClient != nullptr && fdfsClient->fastFds != nullptr) { fdfsClient->rwLock.rdlock(); @@ -127,135 +140,8 @@ strImgUrl = ""; ERR("fdfsClient is nullptr ???"); } InsertToESDB(faceExtractQueueTmp, t_com_sc, i, j, feature, strImgUrl, strBigImgUrl); //拼接json string str_uuid; uuid_t t_uuid; char str[36]; uuid_generate(t_uuid); uuid_unparse(t_uuid, str); str_uuid = str; Json::Value t_json; t_json["Id"] = str_uuid; //主键 std::string feature_base64; feature_base64 = base64.Encode(feature.data(), feature.size()); //#在对比中添加特征值 t_json["FaceFeature"] = feature_base64; t_json["personId"] = "";//关联底库人员id,人脸id t_json["BaseName"] = "";//关联底库表名 //#end // t_json["likePer"] = faceExtractQueueTmp[i].scoredRects[j].score;//人员相似度 Score t_json["likeDate"] = AppUtil::getTimeSecString();//"2018-01-01 01:01:01";//比较时间 t_json["picName"] = ""; t_json["personPicUrl"] = "";//人员图片 store t_json["picAddress"] = getProperty("str_addr");//抓拍地址 DBG("picAddress=" << t_json["picAddress"]); t_json["picMaxUrl"] = "";//大图路径 t_json["picLocalUrl"] = "";//本地路径 t_json["picSmUrl"] = strImgUrl;//人员抓小图 //#todo t_json["picDate"] = faceExtractQueueTmp[i].scoredRects[j].properties["time"]; DBG("picDate=" << t_json["picDate"].asString()); // DBG("timeC ::::B" << t_json["picDate"m_bIsMask].asString()); // t_json["picDate"] = AppUtil::getTimeSecString(); t_json["content"] = ""; //t_json["viType"] = "2";//只有4种类型 1:personface 2:personbody 3:car 4:bicycle 5:none 未知类型 t_json["sdkType"] = std::to_string( m_sdkRule.nSdkType);//只有4种类型 1:personface 2:personbody 3:car 4:bicycle 5:none 未知类型 t_json["personIsHub"] = "4";//1: 报警 2: 可疑 3: 安全 4: 未知 t_json["cluster_id"] = appPref.getStringData("clusterID"); t_json["ack_alarm"] = "0"; //faceExtractElement.setProperty("dev_id", str_device_id); //faceExtractElement.setProperty("cg_id", str_ch_id); t_json["videoNum"] = getProperty("dev_id");//Video设备编号//getProperty("path");//Vide编号 外键 t_json["videoReqNum"] = getProperty("dev_id");//Video设备编号 t_json["ChannlId"] = getProperty("ch_id");//通道id t_json["isDelete"] = "1";//默认1 ,0无效 1有效 //人脸属性 t_json["Age"] = atoi( faceExtractQueueTmp[i].scoredRects[j].properties["age"].c_str());//检测的年龄 应该为空 无检测结果 //#todo 优化 get vector<string> from json t_json["Gender"] = faceExtractQueueTmp[i].scoredRects[j].properties["gender"];//检测的性别 为空 无检测结果 switch (atoi(faceExtractQueueTmp[i].scoredRects[j].properties["gender"].c_str())) { case 0: t_json["Gender"] = "女"; break; case 1: t_json["Gender"] = "男"; break; } t_json["BeautyLevel"] = faceExtractQueueTmp[i].scoredRects[j].properties["beauty"];//检测的美化水平 为空 无检测结果 t_json["SimleLevel"] = faceExtractQueueTmp[i].scoredRects[j].properties["smile"];//检测的微笑水平 为空 无检测结果 t_json["Race"] = "";//检测的种族 应该为空 无检测结果 t_json["videoIp"] = getProperty("local_ip");//当前服务器IP地址 t_json["cluster_id"] = appConfig.getStringProperty("clusterID");//集群id t_json["ack_alarm"] = "0";//ack_alarm是否报警 //#todo 优化 get vector<string> from json switch (atoi(faceExtractQueueTmp[i].scoredRects[j].properties["race"].c_str())) { case 1: t_json["Race"] = "白人"; break; case 2: t_json["Race"] = "黄人"; break; case 3: t_json["Race"] = "黑人"; break; } // DBG(t_json.toStyledString()); t_json["indeviceid"] = appPref.getStringData("fxDevID"); t_json["indevicename"] = appPref.getStringData("fxDevNAME"); std::string strImageKey = faceExtractQueueTmp[i].scoredRects[j].properties["imgKey"]; INFO("SaveImageKey To ES: " << strImageKey); t_json["imgKey"] = strImageKey; try { auto server = m_rpcClient.getServer(); if (!server) { ERR("server is null"); //return; } INFO("Record Video " << strImageKey); server->recordVideo(strImageKey); } catch (std::exception &e) { ERR("Record Video Err: " << strImageKey << " Message: " << e.what()); //return; } auto faceSearchServer = faceSearchRpcClient.getServer(); if (!faceSearchServer) { ERR("faceSearchServer is null"); EsDBTool pManagerEsDB(appPref.getStringData("ipAdd"), appPref.getIntData("ipPort")); bool retface = false; retface = pManagerEsDB.insertData("videopersons", "perVideoPicture", t_json.toStyledString(), str_uuid); // if (retface) { // INFO("facedb success"); // } else { // ERR("facedb fail"); // } } else { INFO("send faceSearchTopN "); auto faceSearchResults = faceSearchServer->faceSearchTopN(feature, t_json.toStyledString(), 2, t_com_sc); } } } } catch (std::exception &e) { @@ -264,7 +150,140 @@ if (!features.empty())fireConnectors(); } void FaceExtractElement::InsertToESDB(const vector<FaceToExtract> &faceExtractQueueTmp, float t_com_sc, int i, int j, FaceDetect::Data &feature, string &strImgUrl, string &strBigImgUrl) { //拼接json string str_uuid; uuid_t t_uuid; char str[36]; uuid_generate(t_uuid); uuid_unparse(t_uuid, str); str_uuid = str; Json::Value t_json; t_json["Id"] = str_uuid; //主键 string feature_base64; feature_base64 = base64.Encode(feature.data(), feature.size()); //#在对比中添加特征值 t_json["FaceFeature"] = feature_base64; t_json["personId"] = "";//关联底库人员id,人脸id t_json["BaseName"] = "";//关联底库表名 //#end // t_json["likePer"] = faceExtractQueueTmp[i].scoredRects[j].score;//人员相似度 Score t_json["likeDate"] = AppUtil::getTimeSecString();//"2018-01-01 01:01:01";//比较时间 t_json["picName"] = ""; t_json["personPicUrl"] = "";//人员图片 store t_json["picAddress"] = getProperty("str_addr");//抓拍地址 DBG("picAddress=" << t_json["picAddress"]); t_json["picMaxUrl"] = strBigImgUrl;//大图路径 t_json["picLocalUrl"] = "";//本地路径 t_json["picSmUrl"] = strImgUrl;//人员抓小图 //#todo t_json["picDate"] = faceExtractQueueTmp[i].scoredRects[j].properties["time"]; DBG("picDate=" << t_json["picDate"].asString()); // DBG("timeC ::::B" << t_json["picDate"m_bIsMask].asString()); // t_json["picDate"] = AppUtil::getTimeSecString(); t_json["content"] = ""; //t_json["viType"] = "2";//只有4种类型 1:personface 2:personbody 3:car 4:bicycle 5:none 未知类型 t_json["sdkType"] = to_string( m_sdkRule.nSdkType);//只有4种类型 1:personface 2:personbody 3:car 4:bicycle 5:none 未知类型 t_json["personIsHub"] = "4";//1: 报警 2: 可疑 3: 安全 4: 未知 t_json["cluster_id"] = appPref.getStringData("clusterID"); t_json["ack_alarm"] = "0"; //faceExtractElement.setProperty("dev_id", str_device_id); //faceExtractElement.setProperty("cg_id", str_ch_id); t_json["videoNum"] = getProperty("dev_id");//Video设备编号//getProperty("path");//Vide编号 外键 t_json["videoReqNum"] = getProperty("dev_id");//Video设备编号 t_json["ChannlId"] = getProperty("ch_id");//通道id t_json["isDelete"] = "1";//默认1 ,0无效 1有效 //人脸属性 t_json["Age"] = atoi( faceExtractQueueTmp[i].scoredRects[j].properties["age"].c_str());//检测的年龄 应该为空 无检测结果 //#todo 优化 get vector<string> from json t_json["Gender"] = faceExtractQueueTmp[i].scoredRects[j].properties["gender"];//检测的性别 为空 无检测结果 switch (atoi(faceExtractQueueTmp[i].scoredRects[j].properties["gender"].c_str())) { case 0: t_json["Gender"] = "女"; break; case 1: t_json["Gender"] = "男"; break; } t_json["BeautyLevel"] = faceExtractQueueTmp[i].scoredRects[j].properties["beauty"];//检测的美化水平 为空 无检测结果 t_json["SimleLevel"] = faceExtractQueueTmp[i].scoredRects[j].properties["smile"];//检测的微笑水平 为空 无检测结果 t_json["Race"] = "";//检测的种族 应该为空 无检测结果 t_json["videoIp"] = getProperty("local_ip");//当前服务器IP地址 t_json["cluster_id"] = appConfig.getStringProperty("clusterID");//集群id t_json["ack_alarm"] = "0";//ack_alarm是否报警 //#todo 优化 get vector<string> from json switch (atoi(faceExtractQueueTmp[i].scoredRects[j].properties["race"].c_str())) { case 1: t_json["Race"] = "白人"; break; case 2: t_json["Race"] = "黄人"; break; case 3: t_json["Race"] = "黑人"; break; } // DBG(t_json.toStyledString()); t_json["indeviceid"] = appPref.getStringData("fxDevID"); t_json["indevicename"] = appPref.getStringData("fxDevNAME"); string strImageKey = faceExtractQueueTmp[i].scoredRects[j].properties["imgKey"]; INFO("SaveImageKey To ES: " << strImageKey); t_json["imgKey"] = strImageKey; try { auto server = m_rpcClient.getServer(); if (!server) { ERR("server is null"); //return; } INFO("Record Video " << strImageKey); server->recordVideo(strImageKey); } catch (exception &e) { ERR("Record Video Err: " << strImageKey << " Message: " << e.what()); //return; } auto faceSearchServer = faceSearchRpcClient.getServer(); if (!faceSearchServer) { ERR("faceSearchServer is null"); EsDBTool pManagerEsDB(appPref.getStringData("ipAdd"), appPref.getIntData("ipPort")); bool retface = false; retface = pManagerEsDB.insertData("videopersons", "perVideoPicture", t_json.toStyledString(), str_uuid); // if (retface) { // INFO("facedb success"); // } else { // ERR("facedb fail"); // } } else { INFO("send faceSearchTopN "); auto faceSearchResults = faceSearchServer->faceSearchTopN(feature, t_json.toStyledString(), 2, t_com_sc); } } std::vector<::FaceDetect::Data> FaceExtractElement::getFeatures() const { return features; } QiaoJiaSystem/StructureApp/FaceExtractElement.h
@@ -14,6 +14,7 @@ #include <mutex> #include <jsoncpp/json/json.h> #include "DBStruct.h" #define VECTOR_MAX 50 class QSharedMemory; @@ -30,7 +31,7 @@ class FaceExtractElement : public TimerElement { public: FaceExtractElement(std::string shareMemoryName,const SdkRule& rule); FaceExtractElement(std::string shareMemoryName, const SdkRule &rule); //FaceExtractElement(std::string shareMemoryName,const SdkRule& rule,SaveVideoRpcClient_t& rpcClient); ~FaceExtractElement(); @@ -57,10 +58,13 @@ // AlarmServerInterface::TableNames tableNames; std::vector<::FaceDetect::Data> features; cv::Mat m_image; Base64 base64; SdkRule m_sdkRule; SaveVideoRpcClient_t m_rpcClient; void InsertToESDB(const vector<FaceToExtract> &faceExtractQueueTmp, float t_com_sc, int i, int j, FaceDetect::Data &feature, string &strImgUrl, string &strBigImgUrl); }; QiaoJiaSystem/VideoToImageMulth/RtspAnalysManager.cpp
@@ -478,7 +478,7 @@ // INFO("Save Succeed Cam: " << camId << " ImageKey: " << imageName); item->second->SaveImage(imageName, img); } else { ERR("Save Failed Cam: " << camId << " ImageKey: " << imageName); // ERR("Save Failed Cam: " << camId << " ImageKey: " << imageName); } // m_imgRedisCRwLock.unlock(); // INFO("MYH DEBUG HERE");