#include "DataDealTwoEngine.h"

using namespace ai_matrix;

extern bool g_bNoDealStepTwoFlag;

DataDealTwoEngine::DataDealTwoEngine() {}

DataDealTwoEngine::~DataDealTwoEngine() {}

APP_ERROR DataDealTwoEngine::Init()
{
    strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
    strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1";
    strPort2_ = engineName_ + "_" + std::to_string(engineId_) + "_2";
    strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path");
    iIntervalTime_ = 40 *1000;
    iSplitSpanPX_ = MyYaml::GetIns()->GetIntValue("gc_split_frame_span_px");

    dataSourceConfig_ = MyYaml::GetIns()->GetDataSourceConfigById(engineId_); //获取摄像机参数
    mapUseDataSouceCfg_ = MyYaml::GetIns()->GetUseDataSourceConfig();

    std::string delimiter(",");
    for (auto iter = mapUseDataSouceCfg_.begin(); iter!=mapUseDataSouceCfg_.end(); iter++)
    {
        int iSourceId = iter->first;
        std::vector<std::string> vecSplit = MyUtils::getins()->split(iter->second.strTarget, delimiter);

        std::vector<std::string> vecPushPorts;
        for (auto iter = vecSplit.begin(); iter != vecSplit.end(); iter++)
        {
            if (*iter == "NUM")
            {
                vecPushPorts.push_back(strPort0_);
            }
            else if (*iter == "CHKDATE")
            {
                vecPushPorts.push_back(strPort1_);
            }
            else if(*iter == "CONTAINER" || *iter == "CONTAINER_T")
            {
                vecPushPorts.push_back(strPort2_);
            }
        }
        mapSourcePushPort_[iSourceId] = vecPushPorts;
    }

    InitParam();
    LogInfo << "engineId_:" << engineId_ << " DataDealTwoEngine Init ok";
    return APP_ERR_OK;
}

APP_ERROR DataDealTwoEngine::DeInit()
{

    LogInfo << "engineId_:" << engineId_ << " DataDealTwoEngine DeInit ok";
    return APP_ERR_OK;
}

/**
* 参数初始化(列车结束时需调用)
* inParam : N/A
* outParam: N/A
* return  : N/A
*/
void DataDealTwoEngine::InitParam()
{
    iTrainIndex_ = 1;
    iDirection_ = DIRECTION_UNKNOWN;
    iDirectionAndFirst_ = DO_NOT_KNOW_DIRECTION;
    iLastSpaceX_ = 0;
    iLastSpaceFrameid_ = 0;
    iSpaceType_ = 0;   
}

/**
* 图片数据解码
* inParam : RawData &rawData                            :图片数据
* outParam: std::shared_ptr<DecodedData> pDecodedData   :解码数据
* return  : true(编码成功)/false(编码失败)
*/
bool DataDealTwoEngine::GetJpegdOut(std::shared_ptr<DecodedData> pDecodedData, RawData &rawData)
{
    int iRet = APP_ERR_OK;
    return true;
}

/**
* 获取大框信息
* inParam : N/A
* outParam: N/A
* return  : N/A
*/
void DataDealTwoEngine::GetPostSubDatas(std::vector<PostSubData> &vecPostSubData, Json::Value &jvFrameInfo,
                                        Target tar, Json::Value &jvOneSplit)
{
    std::string strKey;
    switch (tar)
    {
    case NUM:
        strKey = "step1Num";
        break;
    case PRO:
        strKey = "step1Pro";
        break;
    case CHKDATE:
        strKey = "step1ChkDate";
        break;
    case CONTAINER:
        strKey = "step1Container";
        break;
    default:
        break;
    }

    if (strKey.empty())
    {
        return;
    }

    if (!jvFrameInfo.isMember(strKey.c_str()))
    {
        return;
    }

    float fSplitCenterX = jvOneSplit["splitX"].asFloat();
    int iValidType = jvOneSplit["validType"].asInt();

    Json::Value &jsArray = jvFrameInfo[strKey.c_str()];
    for (int i = 0; i < jsArray.size(); i++)
    {
        float fCenterX = jsArray[i]["ltx"].asFloat() + (jsArray[i]["rbx"].asFloat() - jsArray[i]["ltx"].asFloat()) / 2;
        if (jvOneSplit["useY"].asBool())
        {
            fCenterX = jsArray[i]["lty"].asFloat() + (jsArray[i]["rby"].asFloat() - jsArray[i]["lty"].asFloat()) / 2;
        }

        bool bChkFlag = false;
        if(iValidType == VALID_ALL)
        {
            bChkFlag = true;
        }
        else if(iValidType == VALID_LEFT && fCenterX < fSplitCenterX)
        {
            bChkFlag = true;
        }
        else if(iValidType == VALID_RIGHT && fCenterX > fSplitCenterX)
        {
            bChkFlag = true;
        }

        if (bChkFlag)
        {
            SingleData sdInfo;
            sdInfo.iClassId = jsArray[i]["classid"].asInt();
            sdInfo.fScore = jsArray[i]["score"].asFloat();
            sdInfo.fLTX = jsArray[i]["ltx"].asFloat();
            sdInfo.fLTY = jsArray[i]["lty"].asFloat();
            sdInfo.fRBX = jsArray[i]["rbx"].asFloat();
            sdInfo.fRBY = jsArray[i]["rby"].asFloat();
            sdInfo.fClear = jsArray[i]["clear"].asFloat();

            PostSubData postSubData;
            postSubData.iBigClassId = sdInfo.iClassId;
            postSubData.iTargetType = tar;
            if (tar == NUM && postSubData.iBigClassId == 0)
            {
                postSubData.iTargetType = HEAD;
            }
            postSubData.vecSingleData.emplace_back(sdInfo);
            postSubData.step1Location.fLTX = sdInfo.fLTX;
            postSubData.step1Location.fLTY = sdInfo.fLTY;
            postSubData.step1Location.fRBX = sdInfo.fRBX;
            postSubData.step1Location.fRBY = sdInfo.fRBY;
            vecPostSubData.emplace_back(postSubData);
        }
    }
}

/**
* 获取主摄像头车厢间隔坐标信息
* inParam : N/A
* outParam: N/A
* return  : N/A
*/
void DataDealTwoEngine::GetMainSplitInfo(Json::Value &jvMainSplit, std::shared_ptr<ProcessData> pProcessData,
                                         Json::Value &jvFrameInfo, std::shared_ptr<TrainRange> pTrainRange)
{
    if (pProcessData->iDataSource != 0)
    {
        return;
    }

    Json::Value jvModelSpace;
    if (jvFrameInfo.isMember("step1Space"))
    {
        jvModelSpace = jvFrameInfo["step1Space"][0];
    }

    int iValidType = VALID_ALL;             //图像上大框有效类型 {0-全部有效; 1-左边有效; 2-右边有效}
    int iSpaceX = 0;                        //图像上车厢间隔位置
    bool bNeedNum = true;                   //图像上车号框是否有效
    bool bNeedPro = true;                   //图像上属性框是否有效
    bool bNeedChkDate = true;               //图像定检期框是否有效
    bool bNeedContainer = true;             //图像集装箱框是否有效
    bool bOtherSideNeedNum = true;          //另一侧图像上车号框是否有效
    bool bOtherSideNeedPro = true;          //另一侧图像上属性框是否有效
    bool bOtherSideNeedChkDate = true;      //另一侧图像上定检期框是否有效
    bool bOtherSideNeedContainer = true;    //另一侧图像上集装箱框是否有效

    if (!jvModelSpace.empty())
    {
        iSpaceX = jvModelSpace["ltx"].asFloat() + (jvModelSpace["rbx"].asFloat() - jvModelSpace["ltx"].asFloat()) / 2;
        /*
        第一节只有结束间隔;
        开始帧间隔为开始间隔;
        向左行驶且当前间隔大于上次间隔为结束间隔，向右行驶当前间隔小于上次间隔为结束间隔。
        */
        bool bIntervalFlag = ((int)(pProcessData->iFrameId - iLastSpaceFrameid_) > dataSourceConfig_.iSkipInterval * 2);
        if (iTrainIndex_ == 1)
        {
            iSpaceType_ = 2;
        }
        else if (pTrainRange->iStartFrameId == pProcessData->iFrameId)
        {
            iSpaceType_ = 1;
        }
        else if ((pProcessData->iDirection == DIRECTION_LEFT && (iLastSpaceX_ < iSpaceX - iSplitSpanPX_) && bIntervalFlag) ||
                 (pProcessData->iDirection == DIRECTION_RIGHT && (iLastSpaceX_ - iSplitSpanPX_ > iSpaceX) && bIntervalFlag))
        {
            iSpaceType_ = 2;
        }

        if (iSpaceType_ == 1)
        {
            iValidType = pProcessData->iDirection == DIRECTION_LEFT ? VALID_RIGHT : VALID_LEFT;
        }
        else if (iSpaceType_ == 2)
        {
            iValidType = pProcessData->iDirection == DIRECTION_LEFT ? VALID_LEFT : VALID_RIGHT;
        }
        LogDebug << " frameid:" << pProcessData->iFrameId
                 << " 车节:" << pProcessData->iTrainIndex << " iSpaceType_:" << iSpaceType_
                 << " iSpaceX:" << iSpaceX << " iLastSpaceX_:" << iLastSpaceX_
                 << " iLastSpaceFrameid_:" << iLastSpaceFrameid_ << " bIntervalFlag:" << bIntervalFlag;
        iLastSpaceX_ = iSpaceX;
        iLastSpaceFrameid_ =  pProcessData->iFrameId;
    }

    jvMainSplit["validType"] = iValidType;
    jvMainSplit["splitX"] = iSpaceX;
    jvMainSplit["needNum"] = bNeedNum;
    jvMainSplit["needPro"] = bNeedPro;
    jvMainSplit["needChkDate"] = bNeedChkDate;
    jvMainSplit["needContainer"] = bNeedContainer;
    jvMainSplit["otherSideNeedNum"] = bOtherSideNeedNum;
    jvMainSplit["otherSideNeedPro"] = bOtherSideNeedPro;
    jvMainSplit["otherSideNeedChkDate"] = bOtherSideNeedChkDate;
    jvMainSplit["otherSideNeedContainer"] = bOtherSideNeedContainer;
    jvMainSplit["mainWidth"] = pProcessData->iWidth;
    jvMainSplit["mainHeight"] = pProcessData->iHeight;

    if (pProcessData->bIsEnd)
    {
        iLastSpaceX_ = 0;
        iLastSpaceFrameid_ = 0;
        iSpaceType_ = 0;
    }
}

/**
* 获取辅摄像头车厢间隔坐标信息
* inParam : N/A
* outParam: N/A
* return  : N/A
*/
void DataDealTwoEngine::GetSubSplitInfoByMain(Json::Value &jvOneSplit, std::shared_ptr<ProcessData> pProcessData, Json::Value &jvFrameInfo)
{
    if (pProcessData->iDataSource == 1)
    {
        if (pProcessData->iDirection == DIRECTION_RIGHT)
        {
            //向右行驶时，间隔坐标尽可能小一些，把未完全对其的定检期信息包含进来。
            jvOneSplit["splitX"] = jvOneSplit["splitX"].asInt() - 100;
        }
    }
    else if (pProcessData->iDataSource == 2)
    {
        //顶部集装箱的重设splitX相关逻辑
        if (jvOneSplit["rotate"].asInt() == 90)
        {
            jvOneSplit["useY"] = true;
            if (pProcessData->iHeight != jvOneSplit["mainWidth"].asInt())
            {
                jvOneSplit["splitX"] = jvOneSplit["splitX"].asInt() * pProcessData->iHeight / jvOneSplit["mainWidth"].asInt();
            }

            //顶部有间隔时，使用顶部间隔。
            if (jvFrameInfo.isMember("step1TopSpace"))
            {
                Json::Value jvModelSpace = jvFrameInfo["step1TopSpace"][0];
                int iSpaceX = jvModelSpace["lty"].asFloat() + (jvModelSpace["rby"].asFloat() - jvModelSpace["lty"].asFloat()) / 2;
                LogDebug << "sourceid" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " use TopSpace splitX:"
                         << jvOneSplit["splitX"].asInt() << " newsplitX:" << iSpaceX;
                jvOneSplit["splitX"] = iSpaceX;

                //如果validType为0，则说明主摄像头间隔还未识别到结束间隔，则按顶部摄像头设置validType
                if (jvOneSplit["validType"] == VALID_ALL)
                {
                    jvOneSplit["validType"] = pProcessData->iDirection == DIRECTION_LEFT ? VALID_LEFT : VALID_RIGHT;
                    LogDebug << "sourceid" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId
                             << "reset validType:" << jvOneSplit["validType"].asInt();
                }
            }
        }
    }
    else if (pProcessData->iDataSource == 3 || pProcessData->iDataSource == 4)
    {
        jvOneSplit["splitX"] = (int)(pProcessData->iWidth - jvOneSplit["splitX"].asInt());
        int iValidType = jvOneSplit["validType"].asInt();
        iValidType = iValidType == VALID_ALL ? iValidType : (iValidType == VALID_LEFT ? VALID_RIGHT : VALID_LEFT);
        jvOneSplit["validType"] = iValidType;
        jvOneSplit["needNum"] = jvOneSplit["otherSideNeedNum"].asBool();
        jvOneSplit["needPro"] = jvOneSplit["otherSideNeedPro"].asBool();
        jvOneSplit["needChkDate"] = jvOneSplit["otherSideNeedChkDate"].asBool();
        jvOneSplit["needContainer"] = jvOneSplit["otherSideNeedContainer"].asBool();

        if (pProcessData->iDataSource == 4 && pProcessData->iDirection == DIRECTION_LEFT)
        {
            jvOneSplit["splitX"] = jvOneSplit["splitX"].asInt() + 100;
        }
    }
}

/**
* 获取大框有效方式和车厢间隔坐标
* inParam : N/A
* outParam: N/A
* return  : N/A
*/
void DataDealTwoEngine::GetValidTypeAndSplit(Json::Value &jvOneSplit, Json::Value &jvMainSplit, 
                                            std::shared_ptr<ProcessData> pProcessData, Json::Value &jvFrameInfo, 
                                            std::shared_ptr<TrainRange> pTrainRange)
{
    if (pProcessData->iDataSource == 0)
    {
        GetMainSplitInfo(jvMainSplit, pProcessData, jvFrameInfo, pTrainRange);
        jvOneSplit = jvMainSplit;
    }
    else
    {
        GetSubSplitInfoByMain(jvOneSplit, pProcessData, jvFrameInfo);
    }

//    LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId
//             << " trainIndex:" << pProcessData->iTrainIndex
//             << " validType:" << jvOneSplit["validType"].asInt() << " splitX:" << jvOneSplit["splitX"].asInt()
//             << " needNum:" << jvOneSplit["needNum"].asBool() << " needPro:" << jvOneSplit["needPro"].asBool()
//             << " needChkDate:" << jvOneSplit["needChkDate"].asBool() << " needContainer:" << jvOneSplit["needContainer"].asBool();
}

/**
* 获取大框信息
* inParam : N/A
* outParam: N/A
* return  : N/A
*/
int DataDealTwoEngine::GetPostData(std::shared_ptr<ProcessData> pProcessData, Json::Value &jvFrameInfo, Json::Value &jvOneSplit)
{
    std::shared_ptr<PostData> pPostData = std::make_shared<PostData>();
    pProcessData->pVoidData = std::static_pointer_cast<void>(pPostData);

    if (jvOneSplit["needNum"].asBool())
    {
        GetPostSubDatas(pPostData->vecPostSubData, jvFrameInfo, NUM, jvOneSplit);
    }

    if (jvOneSplit["needPro"].asBool())
    {
        GetPostSubDatas(pPostData->vecPostSubData, jvFrameInfo, PRO, jvOneSplit);
    }

    if (jvOneSplit["needChkDate"].asBool())
    {
        /*
        向右行驶且间隔右边数据有效时，此时画面就1个定检期，画面上的定检期信息全部有效。
        向左行驶且间隔左边数据有效时，此时画面就1个定检期，画面上的定检期信息全部有效。
        */
        int iValidTypeTemp = jvOneSplit["validType"].asInt();

        if ((iValidTypeTemp == VALID_RIGHT && pProcessData->iDataSource == 1 && pProcessData->iDirection == DIRECTION_RIGHT) ||
            (iValidTypeTemp == VALID_RIGHT && pProcessData->iDataSource == 4 && pProcessData->iDirection == DIRECTION_LEFT) ||
            (iValidTypeTemp == VALID_LEFT && pProcessData->iDataSource == 1 && pProcessData->iDirection == DIRECTION_LEFT) ||
            (iValidTypeTemp == VALID_LEFT && pProcessData->iDataSource == 4 && pProcessData->iDirection == DIRECTION_RIGHT))
        {
            jvOneSplit["validType"] = 0;
        }
        GetPostSubDatas(pPostData->vecPostSubData, jvFrameInfo, CHKDATE, jvOneSplit);
        jvOneSplit["validType"] = iValidTypeTemp;
    }

    if (jvOneSplit["needContainer"].asBool())
    {
        GetPostSubDatas(pPostData->vecPostSubData, jvFrameInfo, CONTAINER, jvOneSplit);
    }

    return pPostData->vecPostSubData.size();
}

/**
* push数据到队列，队列满时则休眠一段时间再push。
* inParam : const std::string strPort                           push的端口
          : const std::shared_ptr<ProcessData> &pProcessData    push的数据
* outParam: N/A
* return  : N/A
*/
void DataDealTwoEngine::PushData(const std::string &strPort, const std::shared_ptr<ProcessData> &pProcessData)
{
    while (true)
    {
        int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast<void>(pProcessData));
        if (iRet != 0)
        {
            LogDebug << "sourceid:" << pProcessData->iDataSource << " frameid:" << pProcessData->iFrameId << " push fail iRet:" << iRet;
            if (iRet == 2)
            {
                usleep(10000); // 10ms
                continue;
            }
        }
        break;
    }
}

/**
* 构造处理数据并push
* inParam : N/A
* outParam: N/A
* return  : N/A
*/
void DataDealTwoEngine::MakeProcessData(std::shared_ptr<TrainRange> pTrainRange)
{
    int iRet = APP_ERR_OK;
    int iDataNO = 1;

    std::string strDataDir = strResultPath_ + pTrainRange->strTrainDate + "/" + pTrainRange->strTrainName + "/";
    for (int iFrameId = pTrainRange->iStartFrameId; iFrameId <= pTrainRange->iEndFrameId; iFrameId += dataSourceConfig_.iSkipInterval)
    {
        Json::Value jvMainSplit;    //主摄像头车厢间隔坐标信息
        int iStatus = TRAINSTATUS_RUN;
        int iTagTotalCnt = 0;
        for (auto iter = mapUseDataSouceCfg_.begin(); iter != mapUseDataSouceCfg_.end(); iter++)
        {
            int iSourceId = iter->first;
            char szCameraNo[5] = {0};
            sprintf(szCameraNo, "%03d/", iSourceId + 1);
            bool bIsEndFlag = (pTrainRange->iEndFrameId == iFrameId);

//            LogInfo << "sourceid:" << iSourceId << " StepTwo MakeProcessData trainIndex:" << pTrainRange->iTrainIndex
//                    << " iFrameId:" << iFrameId << " bIsEndFlag:" << bIsEndFlag;
            std::string strImgName = strDataDir + szCameraNo + std::to_string(iFrameId);
            strImgName += (iter->second.iRotate != 0) ? "_rotate.jpg" : ".jpg";
            std::string strFileName = strDataDir + szCameraNo + std::to_string(iFrameId) + ".txt";

            // 获取大框信息
            Json::Value jvFrameInfo;
            bool bReadFlag = MyUtils::getins()->ReadJsonInfo(jvFrameInfo, strFileName, 0);
            if (!bIsEndFlag && !bReadFlag)
            {
                //非车厢结束帧且没有txt信息时不处理。
                continue;
            }

            iStatus = (iSourceId == 0 ? jvFrameInfo["status"].asInt() : iStatus);

            // 构造处理数据信息
            std::shared_ptr<ProcessData> pProcessData = std::make_shared<ProcessData>();
            pProcessData->iDataSource = iSourceId;
            pProcessData->iFrameId = iFrameId;
            pProcessData->strTrainDate = pTrainRange->strTrainDate;
            pProcessData->strTrainName = pTrainRange->strTrainName;
            pProcessData->bIsEnd = bIsEndFlag;
            pProcessData->iStatus = iStatus;
            pProcessData->iDirection = iDirection_;
            pProcessData->iDataNO = iDataNO;
            pProcessData->iTrainIndex = pTrainRange->iTrainIndex;
            pProcessData->bIsTrainEnd = pTrainRange->bIsEnd;
            pProcessData->strPicFilePath = strImgName;
            pProcessData->i64TimeStamp = jvFrameInfo["timeStamp"].asUInt64();
            pProcessData->iWidth = jvFrameInfo["width"].asInt();
            pProcessData->iHeight = jvFrameInfo["height"].asInt();

            Json::Value jvOneSplit;
            jvOneSplit = jvMainSplit;
            jvOneSplit["rotate"] = iter->second.iRotate;
            GetValidTypeAndSplit(jvOneSplit, jvMainSplit, pProcessData, jvFrameInfo, pTrainRange);

            // 获取有效的大框信息
            int iRetCnt = GetPostData(pProcessData, jvFrameInfo, jvOneSplit);
            iTagTotalCnt += iRetCnt;

            if (iRetCnt > 0 && iStatus == TRAINSTATUS_RUN)
            {
                cv::Mat cvframe = cv::imread(pProcessData->strPicFilePath);
                int iBufferSize = pProcessData->iWidth * pProcessData->iHeight * 3;
                void *pBGRBufferobj = nullptr;
                pBGRBufferobj = new uint8_t[iBufferSize];
                memcpy(pBGRBufferobj, cvframe.data, iBufferSize);
                pProcessData->pData.reset(pBGRBufferobj, [](void *data){if(data) {delete[] data; data = nullptr;}});
                pProcessData->iSize = iBufferSize;
            }

            std::vector<std::string> vecPushPorts = mapSourcePushPort_[iSourceId];
            for (int iPort = 0; iPort < vecPushPorts.size(); iPort++)
            {
                if (iPort == vecPushPorts.size() - 1)
                {
                    //iRet = outputQueMap_[vecPushPorts[iPort]]->push(std::static_pointer_cast<void>(pProcessData), true);
                    PushData(vecPushPorts[iPort], pProcessData);
                    continue;
                }
                std::shared_ptr<ProcessData> pNewProcessData = std::make_shared<ProcessData>();
                *pNewProcessData = *pProcessData;
                //iRet = outputQueMap_[vecPushPorts[iPort]]->push(std::static_pointer_cast<void>(pNewProcessData), true);
                PushData(vecPushPorts[iPort], pNewProcessData);
            }
        }

        iDataNO++;
        //每组处理数据需间隔一定时间 (运行状态且有第一步结果需休眠，否则直接处理后面的数据)
        if (iStatus == TRAINSTATUS_RUN && iTagTotalCnt != 0)
        {
            usleep(iIntervalTime_);
        }
        while (g_bNoDealStepTwoFlag)
        {
            usleep(iIntervalTime_);
        }
    }
}

APP_ERROR DataDealTwoEngine::Process()
{
    int iRet = APP_ERR_OK;
    while (!isStop_)
    {
        //获取主摄像头车厢划分结果
        std::shared_ptr<void> pVoidData0 = nullptr;
        iRet = inputQueMap_[strPort0_]->pop(pVoidData0);
        if (nullptr == pVoidData0)
        {
            usleep(1000); // 1ms
            continue;
        }

        std::shared_ptr<TrainRange> pTrainRange = std::static_pointer_cast<TrainRange>(pVoidData0);
        LogInfo << "step2 start traindate:" << pTrainRange->strTrainDate << " trainname:" << pTrainRange->strTrainName
                 << " trainindex:" << pTrainRange->iTrainIndex << " startframeid:" << pTrainRange->iStartFrameId 
                 << " endframeid:" << pTrainRange->iEndFrameId << " isEnd:" << pTrainRange->bIsEnd;

        if (iDirection_ == DIRECTION_UNKNOWN)
        {
            /*获取该车辆行驶方向
            特殊场景：车头行驶画面一半后停止，再次反方向驶出画面。再次行驶得场景不会有方向.(因没有大框无法计算方向)
            */
            std::string strFilePath = strResultPath_ + pTrainRange->strTrainDate + "/" + pTrainRange->strTrainName + "/" + "direction.txt";
            int iCnt = 0;
			while (!isStop_ && iCnt < 10)
            {
                Json::Value jvDirectionInfo;
                if (MyUtils::getins()->ReadJsonInfo(jvDirectionInfo, strFilePath))
                {
                    iDirection_ = jvDirectionInfo["direction"].asInt();
                    //按行驶方向获取车号在前还是属性在前
                    if (iDirectionAndFirst_ == DO_NOT_KNOW_DIRECTION && iDirection_ != DIRECTION_UNKNOWN)
                    {
                        iDirectionAndFirst_ = iDirection_ == DIRECTION_LEFT ? dataSourceConfig_.iLeftFirst : dataSourceConfig_.iRightFirst;
                    }
                    break;
                }
                usleep(500 * 1000); // 500ms
				iCnt++;
            }
        }

        /*重置开始帧，结束帧
        开始帧向上取跳帧的倍数，结束帧向下取跳帧的倍数
        例: 车厢开始帧结束帧[50, 125]，则推理的开始帧结束帧为[52, 124]
        */
        int iSkipInterval = dataSourceConfig_.iSkipInterval;
        pTrainRange->iStartFrameId = (pTrainRange->iStartFrameId + iSkipInterval - 1) / iSkipInterval * iSkipInterval;
        pTrainRange->iEndFrameId = pTrainRange->iEndFrameId / iSkipInterval * iSkipInterval;
        if (pTrainRange->iStartFrameId > pTrainRange->iEndFrameId)
        {
            pTrainRange->iStartFrameId = pTrainRange->iEndFrameId;
        }

        //判断第一步是否处理完毕
        char szCameraNo[5] = {0};
        sprintf(szCameraNo, "%03d/", engineId_ + 1);
        std::string strFilePath = strResultPath_ + pTrainRange->strTrainDate + "/" + pTrainRange->strTrainName + "/" + 
                                  szCameraNo + std::to_string(pTrainRange->iEndFrameId) + ".txt";

        int iReadCnt = 0;
		bool bRet = false;
        while (!isStop_ && iReadCnt < 30)
        {
            Json::Value jvFrameInfo;
            bRet = MyUtils::getins()->ReadJsonInfo(jvFrameInfo, strFilePath);
            if (jvFrameInfo["step1Finish"].asBool())
            {
                break;
            }
			usleep(500 * 1000); // 500ms
            iReadCnt++;
        }

        //处理当车厢的每帧信息
        MakeProcessData(pTrainRange);
        // push结果汇总
        iRet = outputQueMap_[engineName_ + "_" + std::to_string(engineId_) + "_9"]->push(std::static_pointer_cast<void>(pTrainRange));
        
        iTrainIndex_++;
        if (pTrainRange->bIsEnd)
        {
            InitParam();
        }
    }

    return APP_ERR_OK;
}
