xuxiuxi
2019-03-05 6e1fff143f2669f7771301d583fff99de7995cdd
Merge branch 'yw.1.2.fixbug' of http://192.168.1.226:10010/r/development/c++ into yw.1.2.fixbug

# Conflicts:
# QiaoJiaSystem/DataManagerServer/http_configserver.cpp
dev_cam
10个文件已添加
13个文件已修改
2192 ■■■■■ 已修改文件
QiaoJiaSystem/CMakeLists.txt 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/DataManagerServer/CMakeLists.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/DataManagerServer/http_configserver.cpp 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/CMakeLists.txt 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp 536 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.h 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/GB28181Server.cpp 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/GB28181Server.h 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/GlobalSignalWaitLock.hpp 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/SpinLock.hpp 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/GB28181DecoderModel/main.cpp 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/LocalDBTool/SqliteFaceEncap.cpp 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/LocalDBTool/SqliteFaceEncap.h 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/LocalDBTool/SqliteToolkit.hpp 118 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/VideoToImageMulth/RtspAnalysManager.cpp 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/VideoToImageMulth/RtspCaptureElement.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/VideoToImageMulth/RtspImageRedis.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/YoloServer/main.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
syncDBTool/ErlangDbTool.cpp 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
syncDBTool/ErlangDbTool.h 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
syncDBTool/SyncDB.hpp 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
QiaoJiaSystem/CMakeLists.txt
@@ -12,8 +12,14 @@
    ./
    ../../BasicPlatForm/
    ../../BasicPlatForm/libs/jsoncpp/include
    ../../BasicPlatForm/libs/glog/include
    ../../BasicPlatForm/libs/opencv/include
    ../../BasicPlatForm/libs/libuuid/include
)
link_directories(
    ../../BasicPlatForm/libs/glog/lib
)
#add_subdirectory(StructureApp)
@@ -28,5 +34,6 @@
#add_subdirectory(VideoToImage)
add_subdirectory(UnitTest)
add_subdirectory(VideoToImageMulth)
add_subdirectory(GB28181DecoderModel)
#add_subdirectory(FaceSearchDbWithImg)
QiaoJiaSystem/DataManagerServer/CMakeLists.txt
@@ -154,7 +154,7 @@
    HCCore
    hcnetsdk
    pthread
    mysqlpp
#    mysqlpp
    )
#add_executable(Apptest
QiaoJiaSystem/DataManagerServer/http_configserver.cpp
@@ -1063,6 +1063,7 @@
        rec.str_username = QString::fromStdString(value["str_username"].asString());
        rec.str_password = QString::fromStdString(value["str_password"].asString());
        rec.str_brand = QString::fromStdString(value["str_brand"].asString());
        rec.str_reserved = QString::fromStdString(value["str_reserved"].asString());
        type = value["n_type"].asInt();
//        rec_sdk_old = db_c.searchCamSdkTableByCamId(rec.str_cam_dev_id);
@@ -1876,31 +1877,87 @@
//    bool ret = false;
    if (reader.parse(content, value)) {
        std::string Uuid = value["uuid"].asString();
        std::string TableType = value["TableType"].asString();
        std::string TableName = value["TableName"].asString();
        int SyncType = atoi(value["SyncType"].asCString());
        std::string BwType = value["BwType"].asString();
        std::string StartTime = value["StartTime"].asString();
        std::string EndTime = value["EndTime"].asString();
        std::string UploadFlag = value["IsSync"].asString();
        UploadFlag = UploadFlag.empty() ? "0" : UploadFlag;
        std::string CmpThreshold = value["threshold"].asString();
        CmpThreshold = CmpThreshold.empty() ? "60" : CmpThreshold;
        std::string Enabled = value["enabled"].asString();
        Enabled = Enabled.empty() ? "1" : Enabled;
        std::string createBy = value["createBy"].asString();
        string str_uuid;
        uuid_t t_uuid;
        char str[36];
        uuid_generate(t_uuid);
        uuid_unparse(t_uuid, str);
        str_uuid = str;
        Uuid = Uuid.empty() ? str_uuid : Uuid;
//        if (createBy == "analyDev") {
//            Uuid = Uuid.empty() ? str_uuid : Uuid;
//        } else if (createBy == "conCemter") {
//            if (Uuid.empty()) {
//                response->write(SimpleWeb::StatusCode::client_error_bad_request, "{\"error\":\"参数错误! \"}");
//                return "";
//            }
//        }
        bool ret = false;
        if (SyncType == 1) {
            //同步库
            ret = erlangDbTool->createDatabase(TableType, TableName, SyncType, BwType, StartTime, EndTime);
        } else if (SyncType == 0) {
            TableName.insert(0, "lt_");
            //本地库
            FieldValues fieldValues;
            fieldValues.insert(std::make_pair("uuid", GetUUId::getUUID()));
            fieldValues.insert(std::make_pair("tableName", TableName));
            fieldValues.insert(std::make_pair("tableDesc", "ceshi"));
            fieldValues.insert(std::make_pair("tableType", TableType));
            fieldValues.insert(std::make_pair("bwType", BwType));
            fieldValues.insert(std::make_pair("startTime", StartTime));
            fieldValues.insert(std::make_pair("endTime", EndTime));
            fieldValues.insert(std::make_pair("create_by", "who"));
            ret = m_SqliteFaceEncap.createTable(TableName, fieldValues);
        FieldValues fieldValues;
        fieldValues.insert(std::make_pair("uuid", Uuid));
        fieldValues.insert(std::make_pair("tableName", TableName));
        fieldValues.insert(std::make_pair("tableDesc", "ceshi"));
        fieldValues.insert(std::make_pair("tableType", TableType));
        fieldValues.insert(std::make_pair("bwType", BwType));
        fieldValues.insert(std::make_pair("startTime", StartTime));
        fieldValues.insert(std::make_pair("endTime", EndTime));
//        #todo
        fieldValues.insert(std::make_pair("create_by", createBy));
        fieldValues.insert(std::make_pair("uploadFlag", UploadFlag));
        fieldValues.insert(std::make_pair("cmpThreshold", CmpThreshold));
        fieldValues.insert(std::make_pair("enabled", Enabled));
        if (TableType == "person") {
            if (SyncType == 1) {
                //同步库
                ret = erlangDbTool->createDatabase(Uuid, fieldValues);
            } else if (SyncType == 0) {
                TableName.insert(0, "lt_");
                //本地库
                ret = m_SqliteFaceEncap.createTable(TableName, fieldValues);
            }
        } else if (TableType == "car") {
            ERR(" not not_implemented");
            response->write(SimpleWeb::StatusCode::server_error_not_implemented, "{\"error\":\"类型错误,未实现! \"}");
            return "";
        } else {
            response->write(SimpleWeb::StatusCode::server_error_not_implemented, "{\"error\":\"类型错误,未识别! \"}");
            return "";
        }
////            #todo 上传。仅黑名单。
////            #TODO 根据createBy判断是否需要上传
//        if (createBy == "analyDev" && BwType == "1") {
////            string &Uuid, string &TableName, string &SyncType, string &StartTime,string &EndTime,
////            string &UploadFlag, string &CmpThreshold, string &Enabled
//            string str_SyncType(to_string(SyncType));
//            UploadTaskToMonitorCenter(Uuid, TableName, str_SyncType, StartTime, EndTime, UploadFlag, CmpThreshold,
//                                      Enabled);
//        }
        erlangDbTool->sendMessage();
        std::string str_result = std::string("{\"result\":").append("\"" + std::to_string(ret) + "\"}");
        return str_result;
QiaoJiaSystem/GB28181DecoderModel/CMakeLists.txt
New file
@@ -0,0 +1,101 @@
cmake_minimum_required(VERSION 3.5)
STRING(REGEX REPLACE ".*/(.*)" "\\1" CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
project(${CURRENT_FOLDER})
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE debug)
add_compile_options(-fPIC)
add_definitions(-DGLOG)
#add_definitions(-DTestCode)
add_definitions(-DDEBUG_ERR -DDEBUG_INFO -fpermissive)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../build)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../build)
# packages
#find_package(CUDA)
#include_directories ("${PROJECT_SOURCE_DIR}")
# nvcc flags
#set(CUDA_NVCC_FLAGS -O3;-G;-g)
#set(CUDA_NVCC_FLAGS -gencode arch=compute_20,code=sm_20;-G;-g)
#set(CUDA_NVCC_FLAGS -gencode arch=compute_52,code=sm_52;-G;-g)
#file(GLOB_RECURSE CURRENT_HEADERS *.h *.hpp *.cuh)
#file(GLOB CURRENT_SOURCES *.cpp *.cu)
#source_group("Include" FILES ${CURRENT_HEADERS})
#source_group("Source" FILES ${CURRENT_SOURCES})
#cuda_add_executable(${PROJECT_NAME} ${CURRENT_HEADERS} ${CURRENT_SOURCES})
#cuda_add_library(${PROJECT_NAME} SHARED ${CURRENT_HEADERS} ${CURRENT_SOURCES})
#cuda_add_library(${PROJECT_NAME} STATIC ${CURRENT_HEADERS} ${CURRENT_SOURCES})
SET(SOURCES
    GlobalSignalWaitLock.hpp
    )
SET(LIBS
    glog
    avformat
    avcodec
    swresample
    swscale
    avutil
    bz2 dl z
    Qt5Core
    opencv_world
    28181sdk
    mysqlclient
    StreamParse
    pthread
    )
include_directories(
    #glog
    ../../../BasicPlatForm/libs/glog/include
    ../../../BasicPlatForm/libs/GB28181/include
    ../../../BasicPlatForm/libs/opencv/include
    ../../../BasicPlatForm/libs/ffmpeg/include
    ../../../BasicPlatForm/basic/util/opencv/
    ../../../BasicPlatForm/basic/debug/
    ../../../BasicPlatForm/
    ../../../BasicPlatForm/basic/pipe_element/ffmpeg/
    /usr/include/x86_64-linux-gnu/qt5
)
link_directories(
    #glog
    /usr/local/lib/
    #glog
    ../../../BasicPlatForm/libs/glog/lib
    ../../../BasicPlatForm/libs/GB28181/libs
    ../../../BasicPlatForm/libs/opencv/lib
    ../../../BasicPlatForm/libs/ffmpeg/lib
)
add_executable(${PROJECT_NAME}
    #    testmain.cpp
    main.cpp
    ./GB28181Server.cpp
    ./FFmpegDecoderJPG.cpp
    VideoCaptureElementWithRtp.cpp
    ../../../BasicPlatForm/basic/timer_counter/Clocktimer.cpp
    ${SOURCES}
    )
target_link_libraries(${PROJECT_NAME}
    ${LIBS}
    )
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp
New file
@@ -0,0 +1,536 @@
//
// Created by ps on 19-1-11.
//
#include <zconf.h>
#include <opencv2/opencv.hpp>
#include "FFmpegDecoderJPG.h"
void BASICGB28181::initFFmpeg() {
    av_register_all();
    avformat_network_init();
}
static bool initFFmpegRet = (BASICGB28181::initFFmpeg(), true);
//MyQueue<BASICGB28181::frameBuffInfo *>  BASICGB28181::FFmpegDecoderJPG::m_rtpQueue;
//cv::Mat BASICGB28181::FFmpegDecoderJPG::m_image;
cv::Mat BASICGB28181::avframe_to_cvmat(AVFrame *frame) {
    AVFrame dst;
    memset(&dst, 0, sizeof(dst));
    int w = frame->width, h = frame->height;
    cv::Mat m = std::move(cv::Mat(h, w, CV_8UC3));
    dst.data[0] = (uint8_t *) m.data;
    avpicture_fill((AVPicture *) &dst, dst.data[0], AV_PIX_FMT_BGR24, w, h);
    struct SwsContext *convert_ctx = NULL;
//    PixelFormat src_pixfmt = (enum PixelFormat) frame->format;
//    PixelFormat dst_pixfmt = AV_PIX_FMT_BGR24;
    convert_ctx = sws_getContext(w, h, frame->format, w, h, AV_PIX_FMT_BGR24,
                                 SWS_FAST_BILINEAR, NULL, NULL, NULL);
    sws_scale(convert_ctx, frame->data, frame->linesize, 0, h,
              dst.data, dst.linesize);
    sws_freeContext(convert_ctx);
    DBG("m.size is " << m.size());
    return m;
}
BASICGB28181::FFmpegDecoderJPG::FFmpegDecoderJPG() : m_buf_size(32768), m_running(false), m_PackageState(false),
                                                     m_readData(false), m_rtpQueue(), frame_number(0),
                                                     first_frame_number(-1) {
}
BASICGB28181::FFmpegDecoderJPG::~FFmpegDecoderJPG() {
    while (m_rtpQueue.count_queue()) {
        m_rtpQueue.popNotWait();
    }
}
bool BASICGB28181::FFmpegDecoderJPG::pushInfo(unsigned char *data, int datalen, const std::string &camIdx) {
    TryCath(
        if (!m_running) {
            ERR(" m_running is false");
            return false;
        }
#ifdef TestCode
        DBG(camIdx << " dataLen is " << datalen);
#endif
        frameBuffInfo *info = new frameBuffInfo();
        info->buff = new unsigned char[datalen];
        info->buffLen = datalen;
        info->camIdx = camIdx;
        memcpy(info->buff, data, datalen);
#ifdef TestCode
        DBG(" m_rtpQueue.push before ");
#endif
        m_rtpQueue.push(info);
#ifdef TestCode
        DBG(" m_rtpQueue.push after ");
#endif
    );
    return true;
}
int BASICGB28181::FFmpegDecoderJPG::read_data(void *opaque, uint8_t *buf, int bufsize) {
#ifdef TestCode
    ClockTimer cl("read_data");
#endif
    FFmpegDecoderJPG *fFmpegDecoderJPG = (FFmpegDecoderJPG *) opaque;
    int len = bufsize;
    int diff = 0;
    do {
//        DBG(" m_rtpQueue.pop before ");
        frameBuffInfo *buffinfo = fFmpegDecoderJPG->m_rtpQueue.pop();
//        DBG(" m_rtpQueue.pop after ");
        diff = len - buffinfo->buffLen;
//        printf("bufsize is :%ld,len is :%ld, datalen:%d \n", bufsize, len, buffinfo->buffLen);
        //帧长大于bufsize
        if (diff < 0) {
//            DBG("/帧长大于bufsize" << diff);
            memcpy(buf + bufsize - len, buffinfo->buff, len);
            frameBuffInfo *info = new frameBuffInfo();
            info->buffLen = buffinfo->buffLen - len;
            info->buff = new uint8_t[buffinfo->buffLen - len]{};
            memcpy(info->buff, buffinfo->buff + len, buffinfo->buffLen - len);
            fFmpegDecoderJPG->m_rtpQueue.push_front_one(info);
            fFmpegDecoderJPG->m_PackageState = true;
        } else if (diff == 0) {
//            DBG("/帧长等于bufsize" << diff);
            memcpy(buf + bufsize - len, buffinfo->buff, buffinfo->buffLen);
            fFmpegDecoderJPG->m_PackageState = false;
        } else if (diff > 0) {
//            DBG("/帧长小于bufsize" << diff);
            memcpy(buf + bufsize - len, buffinfo->buff, buffinfo->buffLen);
            len = len - buffinfo->buffLen;   //还需要填充的大小
            memset(buf + bufsize - len, 0, len);
//            if (fFmpegDecoderJPG->m_PackageState) {
            //不等待填充,直接进行解码
            diff = 0;
            fFmpegDecoderJPG->m_PackageState = false;
//            }
        }
        delete[] buffinfo->buff;
        delete buffinfo;
    } while (diff > 0);
    //#todo 触发信号
//    DBG("emitSigal(\"read_dataOk\") begin");
//    gSignalLock.emitSigal("read_dataOk");
    fFmpegDecoderJPG->m_readData = true;
//    DBG("emitSigal(\"read_dataOk\") after");
    return bufsize;
}
void BASICGB28181::FFmpegDecoderJPG::BareFlowDecoderThd(FFmpegDecoderJPG *p_this) {
    DBG(p_this->m_camIdx << "  BareFlowDecoderThd ok ... gpuIdx is " << p_this->m_gpuIdx);
    p_this->m_running = true;
    av_register_all();
    avformat_network_init();
    AVFormatContext *ic = avformat_alloc_context();
    unsigned char *iobuffer = (unsigned char *) av_malloc(p_this->m_buf_size);
    AVIOContext *avio = avio_alloc_context(iobuffer, p_this->m_buf_size, 0, p_this, p_this->read_data, NULL, NULL);
    ic->pb = avio;
    int err = av_probe_input_buffer(ic->pb, &ic->iformat, nullptr, nullptr, 0, p_this->m_buf_size);
    int err1 = avformat_open_input(&ic, "", NULL, NULL);
    int err2 = avformat_find_stream_info(ic, nullptr);
    int vi = -1;
    for (int i = 0; i < ic->nb_streams; ++i) {
        if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            vi = i;
            break;
        }
    }
    AVStream *stream = ic->streams[vi];
    p_this->video_st = stream;
    AVCodecContext *ctx = avcodec_alloc_context3(nullptr);
    int err3 = avcodec_parameters_to_context(ctx, stream->codecpar);
    AVCodec *codec = avcodec_find_decoder(ctx->codec_id);
    //是否启用GPU
    if (p_this->m_gpuIdx >= 0) {
        if (codec != NULL) {
            char cuvidName[40] = {0};
            sprintf(cuvidName, "%s_cuvid", codec->name);
            if (!strcmp(codec->name, "h264") || !strcmp(codec->name, "h265") || !strcmp(codec->name, "hevc")) {
                AVCodec *codec_cuvid = avcodec_find_decoder_by_name(cuvidName);
                if (codec_cuvid != NULL) {
                    codec = codec_cuvid;
                } else {
//                    return false;
                    ERR("codec_cuvid is NULL");
                }
            }
        }
    }
    int err4 = avcodec_open2(ctx, codec, nullptr);
    AVPacket pkt;
    av_init_packet(&pkt);
    AVFrame *frame = av_frame_alloc();
    unsigned int usleepTime = (1000 / p_this->m_fps) - 12;
    usleepTime *= 1000;
    DBG(" before while <<usleepTime is " << usleepTime);
    while (p_this->m_running) {
#ifdef TestCode
        ClockTimer Test("while time");
#endif
        int err5 = av_read_frame(ic, &pkt);
        //# todo save package
        p_this->frame_number++;
        //DBG("GotPicture "<<m_camId<<":"<<frame_number);
        //放在此处是因为之前放在前面,收到的帧不完成
        p_this->SaveToPacketVector(pkt);
        p_this->CheckSave();
        int err6 = avcodec_send_packet(ctx, &pkt);
        av_packet_unref(&pkt);
        int err7 = avcodec_receive_frame(ctx, frame);
        if ((err7 == AVERROR(EAGAIN)) || (err5 < 0) || (err6 < 0)) {
            ERR(" error << err7:" << err7 << "  err5: " << err5 << " err6: " << err6);
            usleep(40000);
            continue;
        }
//        BASICGB28181::avframe_to_cvmat(frame).copyTo(p_this->m_image);
        p_this->m_image = std::move(BASICGB28181::avframe_to_cvmat(frame));
#ifdef TestCode
        {
//            TestCode
            ClockTimer cl("TestCode");
            std::string strNewTime2 = AppUtil::getTimeUSecString();
            cv::putText(p_this->m_image, strNewTime2, cv::Point(408, 540), cv::HersheyFonts::FONT_HERSHEY_PLAIN,
                        5, cv::Scalar(255, 255, 0), 2);
            std::thread test([&](cv::Mat img, std::string strThing) {
                try {
                    std::string strNewTime = "tmpDec/";
                    strNewTime.append(p_this->m_camIdx + "_").append(strThing).append(".jpg");
//                    cv::imwrite(strNewTime, p_this->m_image);
                } catch (std::exception ex) {
                    ERR(ex.what());
                }
            }, p_this->m_image, strNewTime2);
            test.detach();
        }
#endif
        //#todo send to other thd
#ifdef TestCode
        DBG("emitSigal(\"DecoderImageOK\") begin");
#endif
        gSignalLock.emitSigal(p_this->m_camIdx + "DecoderImageOK");
//#ifdef TestCode
//        DBG("emitSigal(\"DecoderImageOK\") after");
//#endif
        DBG("emitSigal(\"DecoderImageOK\") after");
        DBG("p_this->m_camIdx is " << p_this->m_camIdx << " queue size is " << p_this->m_rtpQueue.count_queue());
#ifdef TestCode
        {
            ClockTimer cl("waitTime");
            int loop = 0;
            //#TODO
//            while ((loop++ < 3000) && !(p_this->m_readData)) {
//                usleep(10);
//            }
            usleep(30000);
            DBG("p_this->m_readData is " << p_this->m_readData << "  loop is " << loop << " queue size is "
                                         << p_this->m_rtpQueue.count_queue());
            p_this->m_readData = false;
//        usleep(12000);
        }
#else
        usleep(usleepTime);
#endif
    }
    DBG(" after while ");
    av_frame_free(&frame);
}
bool BASICGB28181::FFmpegDecoderJPG::startThd(const std::string &camIdx, const int &fps, const int &gpuIdx) {
    TryCath(
        DBG(camIdx << "  FFmpegDecoderJPG startThd ... gpuIdx is " << gpuIdx);
        m_gpuIdx = gpuIdx;
        m_fps = fps;
        if (gpuIdx >= 0) {
            setenv("CUDA_VISIBLE_DEVICES", std::to_string(gpuIdx).c_str(), 0);
        }
        m_camIdx = camIdx;
        std::thread t_BareFlowDecoder(BareFlowDecoderThd, this);
        t_BareFlowDecoder.detach();
    );
    return true;
}
bool BASICGB28181::FFmpegDecoderJPG::stopThd() {
    TryCath(
        DBG(m_camIdx << "  FFmpegDecoderJPG stopThd ... ");
        m_running = false;
    );
    return true;
}
bool BASICGB28181::FFmpegDecoderJPG::getRunning() {
    return m_running;
}
cv::Mat BASICGB28181::FFmpegDecoderJPG::getImage() {
    return m_image;
}
std::string BASICGB28181::FFmpegDecoderJPG::GetImageName() {
    ImageName_s_t st;
    st.m_camId = this->m_camIdx;
    st.m_frameId = this->m_frameIndex;
    st.m_timeStamp = AppUtil::GetTimeWithHyphen();
    return st.toString();
}
bool BASICGB28181::FFmpegDecoderJPG::SaveVideoByImageName(const std::string &strPath, const std::string &imageName) {
    DBG(" strPath is " << strPath << "  imageName " << imageName);
    ImageName_s_t imgName_s = ImageName_s_t::fromString(imageName);
    if (!imgName_s.Valid()) {
        ERR("Image Name Valid  " << imageName);
        return false;
    }
    m_videoPath = strPath;
    if (m_recordState == STOP_RECORD) {
        m_recordState = RECORDING_VIDEO;
        m_startFrameId = m_endFrameId = imgName_s.m_frameId;
    } else {
        if (imgName_s.m_frameId > m_endFrameId) {
            m_endFrameId = imgName_s.m_frameId;
        }
    }
    if (!m_packetsVec.empty()) {
        if (imgName_s.m_frameId < m_packetsVec[0].m_frameId) {
            ERR("Save Video Failed: PackageFirstID: " << m_packetsVec[0].m_frameId << " ImageId: "
                                                      << imgName_s.m_frameId);
        }
    }
    return true;
}
bool BASICGB28181::FFmpegDecoderJPG::SetMinMaxVideoSeconds(const int minSeconds, const int maxSecond) {
    if (minSeconds < 0 || maxSecond < 0 && minSeconds >= maxSecond) {
        return false;
    } else {
        m_minVideoFrameCount = minSeconds * 25;
        m_maxVideoFrameCount = maxSecond * 25;
        return true;
    }
}
bool BASICGB28181::FFmpegDecoderJPG::CleanToFrameId(int64_t lastFrameId) {
    std::lock_guard<std::mutex> lock(g_mutex);
    if (RECORDING_VIDEO == m_recordState) {
        if (!m_packetsVec.empty()) {
            auto iter = m_packetsVec.begin();
            while (iter->m_frameId < lastFrameId) {
                INFO("DropFrame: " << iter->m_frameId);
                delete iter->m_packet.data;
                iter = m_packetsVec.erase(iter);
            }
        }
    }
    return true;
}
bool BASICGB28181::FFmpegDecoderJPG::CleanOneKeyFrameOneRange() {
    std::lock_guard<std::mutex> lock(g_mutex);
    if (!m_packetsVec.empty() && STOP_RECORD == m_recordState) {
        auto firstFrame = m_packetsVec[0];
        //视频的最短长度有问题,可以考虑修改此处 m_minVideoFrameCount
        if ((m_last_I_FrameId - firstFrame.m_frameId > m_minVideoFrameCount / 2)) {
            auto iter = m_packetsVec.begin();
            delete iter->m_packet.data;
            iter = m_packetsVec.erase(iter);
            while (!(iter->m_packet.flags & AV_PKT_FLAG_KEY)) {
//                INFO("DropFrame: " << iter->m_frameId);
                delete iter->m_packet.data;
                iter = m_packetsVec.erase(iter);
            }
        }
    }
    return true;
}
bool BASICGB28181::FFmpegDecoderJPG::SaveVideo(std::string path, int64_t lastFrameId) {
    std::lock_guard<std::mutex> lock(g_mutex);
    INFO("SaveVideo: " << path);
    if (!m_packetsVec.empty()) {
        startWrite(path.c_str());
        int64_t firstKeyFramePts = m_packetsVec[0].m_packet.pts;
        int64_t firstKeyFrameDts = m_packetsVec[0].m_packet.dts;
        for (const auto &item:m_packetsVec) {
            if (item.m_frameId < lastFrameId) {
                conversion(const_cast<AVPacket *> (&item.m_packet), firstKeyFramePts, firstKeyFrameDts, video_st);
                av_write_frame(m_pOutFmtCtx, &item.m_packet);
            } else {
                break;
            }
        }
        stopWrite();
    }
    return true;
}
bool BASICGB28181::FFmpegDecoderJPG::HandleSave() {
    if (m_recordState == RECORDING_VIDEO) {
        auto firstFrame = m_packetsVec[0];
        VideoName_s_t st;
        st.m_camId = m_camIdx;
        st.m_timeStamp = AppUtil::GetTimeWithHyphen();
        st.m_startFrameId = firstFrame.m_frameId;
        st.m_endFrameId = m_last_I_FrameId - 1;
        //结尾留的已经足够,并且没有新的帧需要录像
        if (m_last_I_FrameId - m_endFrameId > m_minVideoFrameCount / 2) {
//            INFO("LastIFrameID: " << m_last_I_FrameId << "  FirstFrameID: " << st.m_startFrameId << " m_endFrameID: "
//                                  << m_endFrameId << "   MinVideoFrameCount :" << m_minVideoFrameCount);
            m_startFrameId = m_endFrameId = -1;
            SaveVideo(m_videoPath + st.ToVideoName(), m_last_I_FrameId);
            CleanToFrameId(m_last_I_FrameId);
            m_recordState = STOP_RECORD;
        } else {
            //缓冲区中已经有太多的帧了,并且剩余的在缓冲队列的m_last_I_FrameId之后还有需要录像的帧
            if (m_endFrameId - firstFrame.m_frameId > m_maxVideoFrameCount) {
//                INFO("FirstFrameID: " << firstFrame.m_frameId << " m_endFrameID: " << m_endFrameId
//                                      << "   MinVideoFrameCount :" << m_maxVideoFrameCount);
                m_startFrameId = m_last_I_FrameId;
                SaveVideo(m_videoPath + st.ToVideoName(), m_last_I_FrameId);
                CleanToFrameId(m_last_I_FrameId);
            }
        }
    }
    return true;
}
bool BASICGB28181::FFmpegDecoderJPG::CheckSave() {
    if (!m_packetsVec.empty()) {
        if (RECORDING_VIDEO == m_recordState) {
            HandleSave();
            return true;
        }
        return CleanOneKeyFrameOneRange();
    }
}
void BASICGB28181::FFmpegDecoderJPG::SaveToPacketVector(AVPacket &packet) {
    AVPacket newPacket(packet);
    newPacket.data = reinterpret_cast<uint8_t *>(new uint64_t[
    (packet.size + FF_INPUT_BUFFER_PADDING_SIZE) / sizeof(uint64_t) + 1]);
    memcpy(newPacket.data, packet.data, packet.size);
    m_frameIndex++;
    m_packetsVec.push_back({m_frameIndex, newPacket});
    if (newPacket.flags & AV_PKT_FLAG_KEY) {
        m_last_I_FrameId = m_frameIndex;
    }
}
int BASICGB28181::FFmpegDecoderJPG::startWrite(const char *filename) {
    if (video_st == nullptr) {
        printf("video_st instream is null");
        return -1;
    }
    int ret = avformat_alloc_output_context2(&m_pOutFmtCtx, NULL, NULL, filename);
    if (ret < 0) {
        fprintf(stderr, "avformat_alloc_output_context2 failed, errorCode: %d\n", AVERROR(ret));
        return -1;
    }
    /*
    * since all input files are supposed to be identical (framerate, dimension, color format, ...)
    * we can safely set output codec values from first input file
    */
    m_pOutVideo_stream = avformat_new_stream(m_pOutFmtCtx, NULL);
    {
//        AVCodecContext *c;
//        c = m_pOutVideo_stream->codec;
//        c->bit_rate = 400000;
//        c->codec_id = video_st->codec->codec_id;
//        c->codec_type = video_st->codec->codec_type;
//        c->time_base.num = video_st->time_base.num;
//        c->time_base.den = video_st->time_base.den;
//        fprintf(stderr, "time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den);
//        c->width = video_st->codec->width;
//        c->height = video_st->codec->height;
//        c->pix_fmt = video_st->codec->pix_fmt;
//        printf("%d %d %d", c->width, c->height, c->pix_fmt);
//        c->flags = video_st->codec->flags;
//        c->flags |= CODEC_FLAG_GLOBAL_HEADER;
//        c->me_range = video_st->codec->me_range;
//        c->max_qdiff = video_st->codec->max_qdiff;
//
//        c->qmin = video_st->codec->qmin;
//        c->qmax = video_st->codec->qmax;
//
//        c->qcompress = video_st->codec->qcompress;
    }
    ret = avio_open(&m_pOutFmtCtx->pb, filename, AVIO_FLAG_WRITE);
    if (ret < 0) {
        fprintf(stderr, "could not find stream info, errorCode: %d\n", AVERROR(ret));
        return -1;
    }
    avformat_write_header(m_pOutFmtCtx, NULL);
    m_bstartWrite = true;
    m_bFirstKeyFrame = true;
    m_nFirstKeyDts = 0;
    m_nFirstKeyPts = 0;
    return 0;
}
int BASICGB28181::FFmpegDecoderJPG::stopWrite() {
    if (m_pOutFmtCtx == nullptr) return -1;
    av_write_trailer(m_pOutFmtCtx);
    avio_close(m_pOutFmtCtx->pb);
    avcodec_close(m_pOutFmtCtx->streams[0]->codec);
    av_freep(&m_pOutFmtCtx->streams[0]->codec);
    av_freep(&m_pOutFmtCtx->streams[0]);
    av_free(m_pOutFmtCtx);
    m_pOutFmtCtx = nullptr;
    m_bstartWrite = false;
    return 0;
}
void BASICGB28181::FFmpegDecoderJPG::conversion(void *packet, const long int &firstKeyPts, const long int &firstKeyDts,
                                                void *inVideoStream) {
    if ((packet != nullptr) && (inVideoStream != nullptr)) {
        AVStream *inStream = (AVStream *) inVideoStream;
        AVPacket *pkg = static_cast<AVPacket *>(packet);
//            static int a = 0;
//            pkg->dts = a++;
//            pkg->pts = a;
        pkg->pts -= firstKeyPts;
        pkg->dts -= firstKeyDts;
        pkg->pts = av_rescale_q_rnd(pkg->pts, inStream->time_base,
                                    m_pOutVideo_stream->time_base,
                                    (AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkg->dts = av_rescale_q_rnd(pkg->dts, inStream->time_base,
                                    m_pOutVideo_stream->time_base,
                                    (AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkg->duration = av_rescale_q(pkg->duration, inStream->time_base,
                                     m_pOutVideo_stream->time_base);
        pkg->pos = -1;
    }
}
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.h
New file
@@ -0,0 +1,248 @@
//
// Created by ps on 19-1-11.
//
//
// #TODO
// 可以把ffmpeg的操作抽成一个对象
//
#ifndef GB28181SDK_FFMPEGDECODERJPG_H
#define GB28181SDK_FFMPEGDECODERJPG_H
#include <iostream>
#include <unistd.h>
#include <MyQueue.h>
#include <Debug.h>
#include <atomic>
#include "GlobalSignalWaitLock.hpp"
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include <list>
#include "basic_struct_for_video_image.h"
extern "C"
{
#include <libavutil/frame.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfiltergraph.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
#include <mutex>
namespace BASICGB28181 {
#define TryCath(CODE)     try { \
CODE } catch (std::exception ex) { \
ERR(ex.what()); \
return false; \
}
    static void initFFmpeg();
    static cv::Mat avframe_to_cvmat(AVFrame *frame);
    typedef struct _buffInfo {
        uint8_t *buff;
        int buffLen;
        std::string camIdx;
    } frameBuffInfo;
    struct FrameIdPackage_s_t {
        int64_t m_frameId;
        AVPacket m_packet;
    };
    struct FrameRange_s_t {
        int64_t m_startFrameId;
        int64_t m_endFrameId;
        std::string m_videoName;
        FrameRange_s_t() {
            m_startFrameId = 0;
            m_endFrameId = 0;
            m_videoName.clear();
        }
        bool IsFrameIdInRange(int64_t frameId) {
            return m_startFrameId <= frameId && frameId <= m_endFrameId;
        }
    };
    enum RecordState_e_t {
        START_RECORD,
        RECORDING_VIDEO,
        STOP_RECORD,
    };
//    std::map<std::string, MyQueue<frameBuffInfo *> > MapMyQueue;
    static std::mutex g_mutex;
    class FFmpegDecoderJPG {
    public:
        FFmpegDecoderJPG();
        virtual ~FFmpegDecoderJPG();
        /***
         * 放入I帧或者P帧
         * #TODO如果第一帧不是I帧会不会有异常?
         * @param data 帧数据地址
         * @param datalen 数据长度
         * @param camIdx 摄像机id
         * @return
         */
        bool pushInfo(unsigned char *data, int datalen, const std::string &camIdx);
        /***
         * 开启解帧线程
         * @param camIdx 摄像机id
         * @param gpuIdx gpuId
         * @return
         */
        bool startThd(const std::string &camIdx, const int &fps, const int &gpuIdx = -1);
        /***
         * 停止解帧线程
         * @return
         */
        bool stopThd();
        //****************************
        std::string GetImageName();
        //保存imageName所在的视频到strPath的路径下
        bool SaveVideoByImageName(const std::string &strPath, const std::string &imageName);
        //设置录像保存的最短长度和最长长度
        bool SetMinMaxVideoSeconds(const int minSeconds, const int maxSecond);
    private:
        //检查保存,每次保存一帧到数组的时候调用
        bool CheckSave();
        //Function
        bool HandleSave();
        //录像的时候,在视频保存完以后,调用这个函数清空缓存
        bool CleanToFrameId(int64_t lastFrameId);
        //不录像的时候,如果保存了足够多的帧,调用此函数清除最前面的两个I帧之间的数据
        bool CleanOneKeyFrameOneRange();
    private:
        //记录最后一个I帧的位置
        int64_t m_last_I_FrameId = -1;
        //保存视频的路径
        std::string m_videoPath;
        //录像的两种状态,
        RecordState_e_t m_recordState = STOP_RECORD;
        //开始录像的帧ID
        int64_t m_startFrameId = 0;
        //最后一个需要录像的帧ID
        int64_t m_endFrameId = 0;
        //Variable
        // 录像视频的最短长度(帧数)
        int m_minVideoFrameCount = 10 * 25; // 10 seconds
        // 录像视频的最长长度(帧数)
        int m_maxVideoFrameCount = 20 * 25; // 20 seconds;
        int m_maxVectorFrameCount = m_maxVideoFrameCount * 2;
        //对收到的帧进行计数
        int64_t m_frameIndex = 0;
        //将帧保存到帧数组
        void SaveToPacketVector(AVPacket &packet);
        //保存lastFrameId之前的视频保存到path表示的文件中
        bool SaveVideo(std::string path, int64_t lastFrameId);
    public:
        //第一帧必须是I帧
        std::vector<FrameIdPackage_s_t> m_packetsVec;
        //******************
        int64_t frame_number, first_frame_number;
        //打开文件写入文件头
        int startWrite(const char *filename);
        //关闭用startWrite打开的文件
        int stopWrite();
        //对packet做转换
        void conversion(void *packet, const long int &firstKeyPts, const long int &firstKeyDts, void *inVideoStream);
        bool m_bstartWrite = {false};
        bool m_bFirstKeyFrame = {false};
        long int m_nFirstKeyPts = 0;
        long int m_nFirstKeyDts = 0;
        AVFormatContext *m_pOutFmtCtx = {nullptr};
        AVStream *video_st{0};
        AVStream *m_pOutVideo_stream{nullptr};
        //****************************
    public:
        /***
         * 获取线程状态
         * @return
         */
        bool getRunning();
        cv::Mat getImage();
//        #todo send Image func ? thd?
    private:
        int m_buf_size; //32768;
        int m_gpuIdx;
        int m_fps;
        bool m_PackageState;
        std::string m_camIdx;
        MyQueue<frameBuffInfo *> m_rtpQueue;
        cv::Mat m_image;
        std::atomic<bool> m_running;
        bool m_readData;
    private:
        /***
         * ffmpeg读取内存数据回调函数
         * @param opaque
         * @param buf
         * @param bufsize
         * @return
         */
        static int read_data(void *opaque, uint8_t *buf, int bufsize);
        /***
         * 裸流解码函数
         * @param p_this 类指针
         */
        static void BareFlowDecoderThd(FFmpegDecoderJPG *p_this);
    };
}
#endif //GB28181SDK_FFMPEGDECODERJPG_H
QiaoJiaSystem/GB28181DecoderModel/GB28181Server.cpp
New file
@@ -0,0 +1,56 @@
//
// Created by ps on 19-3-1.
//
#include "GB28181Server.h"
bool bGetLoaclRes = {false};
GB28181Server::GB28181Server() {}
GB28181Server::~GB28181Server() {
    C_UnInitSDK();
}
void GB28181Server::setMysqlConnParam(const MysqlDBServerCfg &_MysqlConnParam) {
    memset(&MysqlConnParam, 0, sizeof(MysqlConnParam_T));
    strcpy(MysqlConnParam.Host, _MysqlConnParam.Host.c_str());    //连接数据库的ip地址
    MysqlConnParam.Port = _MysqlConnParam.Port;                        //连接数据库的端口
    strcpy(MysqlConnParam.UserName, _MysqlConnParam.UserName.c_str());        //连接数据库的用户名
    strcpy(MysqlConnParam.Passwd, _MysqlConnParam.Passwd.c_str());        //连接数据库的密码
    strcpy(MysqlConnParam.DBName, _MysqlConnParam.DBName.c_str());    //连接数据库的表名
    MysqlConnParam.DBConnCount = _MysqlConnParam.DBConnCount;                    //连接数据库的数量
}
void GB28181Server::setGBServerParam(const GBServerCfg &_GBServerParam) {
    memset(&GBServerParam, 0, sizeof(GBServerParam_T));
    strcpy(GBServerParam.SvrIp, _GBServerParam.SvrIp.c_str()); // 国标服务的ip地址  (本机的ip地址)
    //strcpy(GBServerParam.SvrNatIp, "222.35.102.22"); //注意: 此处如果没有穿网ip地址不需要配置 (一般部署公网时使用)
    GBServerParam.SvrPort = _GBServerParam.SvrPort; // 国标服务监听的端口
    // 44122500042001000123
    strcpy(GBServerParam.SvrPubID, _GBServerParam.SvrPubID.c_str()); // 国标服务器的ID
    GBServerParam.bMD5Auth = _GBServerParam.bMD5Auth;                            // 是否需要MD5加密
    strcpy(GBServerParam.UserName, _GBServerParam.UserName.c_str()); // 国标服务的用户名    (下级设备注册的用户名)
    strcpy(GBServerParam.Passwd, _GBServerParam.Passwd.c_str());                // 国标服务的密码    (下级设备注册的密码)
    GBServerParam.SubScribeTime = _GBServerParam.SubScribeTime;  // 订阅时间  如果为0 表示不订阅
}
void GB28181Server::setUpperPlatform(const UpperPFCfg &_upperinfo) {
    memset(&upperinfo, 0, sizeof(UpperPlatform_T));
    strcpy(upperinfo.Name, _upperinfo.Name.c_str());
    strcpy(upperinfo.PublicID, _upperinfo.PublicID.c_str());
    strcpy(upperinfo.AuthUserName, _upperinfo.AuthUserName.c_str());
    strcpy(upperinfo.AuthPasswd, _upperinfo.AuthPasswd.c_str());
    strcpy(upperinfo.IpAddr, _upperinfo.IpAddr.c_str());
    upperinfo.Port = _upperinfo.Port;
    upperinfo.RegisterItv = _upperinfo.RegisterItv;
    upperinfo.KeepAliveItv = _upperinfo.KeepAliveItv;
}
bool GB28181Server::initServer() {
    bool iRet = C_InitSDK(&GBServerParam, &MysqlConnParam, NULL, enventcallback);
    sleep(90);
    return iRet;
}
QiaoJiaSystem/GB28181DecoderModel/GB28181Server.h
New file
@@ -0,0 +1,93 @@
//
// Created by ps on 19-3-1.
//
#ifndef GB28181SDK_GB28181SERVER_H
#define GB28181SDK_GB28181SERVER_H
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "28181SDK.h"
#include "SpinLock.hpp"
struct MysqlDBServerCfg {
    std::string Host; //连接数据库的ip地址
    int Port;//连接数据库的端口
    std::string UserName;//连接数据库的用户名
    std::string Passwd;//连接数据库的密码
    std::string DBName;//连接数据库的表名
    int DBConnCount;//连接数据库的数量
};
struct GBServerCfg {
    std::string SvrIp;  // 国标服务的ip地址  (本机的ip地址)
    std::string SvrNatIp;       //注意: 此处如果没有穿网ip地址不需要配置 (一般部署公网时使用)
    int SvrPort;  // 国标服务监听的端口
    std::string SvrPubID; // 国标服务器的ID
    bool bMD5Auth; // 是否需要MD5加密
    std::string UserName;// 国标服务的用户名    (下级设备注册的用户名)
    std::string Passwd; // 国标服务的密码    (下级设备注册的密码)
    int SubScribeTime; // 订阅时间  如果为0 表示不订阅
};
struct UpperPFCfg {
    std::string Name;
    std::string PublicID;
    std::string AuthUserName;
    std::string AuthPasswd;
    std::string IpAddr;
    int Port;
    int RegisterItv;
    int KeepAliveItv;
};
class GB28181Server {
public:
    GB28181Server();
    virtual ~GB28181Server();
    void setMysqlConnParam(const MysqlDBServerCfg &_MysqlConnParam);
    void setGBServerParam(const GBServerCfg &_GBServerParam);
    void setUpperPlatform(const UpperPFCfg &_upperinfo);
    bool initServer();
private:
    // mysql数据库的配置信息
    MysqlConnParam_T MysqlConnParam;
    //  国标服务的配置信息
    GBServerParam_T GBServerParam;
    UpperPlatform_T upperinfo;
    static bool bGetLoaclRes;
private:
    //打印事件回调信息
    static void enventcallback(int eventtype, int eventparam, int datalen, char *data) {
        printf("eventtype:%d, eventparam:%d, datalen:%d, data:%s\n", eventtype, eventparam, datalen, data);
        if (eventtype == 2) {
//            GB28181Server::bGetLoaclRes = true;
        } else if (eventtype == 1 && eventparam == 1) {
            C_GetResource(NULL);
        }
    }
};
#endif //GB28181SDK_GB28181SERVER_H
QiaoJiaSystem/GB28181DecoderModel/GlobalSignalWaitLock.hpp
New file
@@ -0,0 +1,115 @@
//
// Created by pans on 19-1-13.
//
#ifndef GB28181SDK_GLOBALSIGNALWAITLOCK_H
#define GB28181SDK_GLOBALSIGNALWAITLOCK_H
#include <iostream>
#include <basic/util/thread/RWLock.hpp>
//#define TryCath(CODE)     try { \
//CODE } catch (std::exception ex) { \
//ERR(ex.what()); \
//return false; \
//} return true;
#define gSignalLock GlobalSignalWaitLock::getInstance()
//#todo 记录每个信号的wait状态,避免某个信号还在使用却将其删除的情况
class SignalLock {
public:
    SignalLock() : m_signal_cond_mutex(PTHREAD_MUTEX_INITIALIZER),
                   m_signal_cond(PTHREAD_COND_INITIALIZER) {
    }
    virtual ~SignalLock() {
    }
    bool wait() {
        pthread_mutex_lock(&m_signal_cond_mutex);
        pthread_cond_wait(&m_signal_cond, &m_signal_cond_mutex);
        pthread_mutex_unlock(&m_signal_cond_mutex);
    }
    bool emit() {
        pthread_cond_signal(&m_signal_cond);
    }
private:
    pthread_cond_t m_signal_cond;
    pthread_mutex_t m_signal_cond_mutex;
};
class GlobalSignalWaitLock {
public:
//    仅支持一对一,#TODO多对一
    static GlobalSignalWaitLock &getInstance() {
        static GlobalSignalWaitLock globalSignalWaitLock;
        return globalSignalWaitLock;
    }
protected:
    GlobalSignalWaitLock() : m_live(true) {}
    virtual ~GlobalSignalWaitLock() {
        m_slRwLock.wrlock();
        m_signalLock.clear();
        m_slRwLock.unlock();
    }
private:
    bool m_live;
    RWLock m_slRwLock;
    std::map<std::string, SignalLock> m_signalLock;
public:
    bool waitSignal(std::string key) {
        try {
            m_slRwLock.rdlock();
            if (m_signalLock.find(key) == m_signalLock.end()) {
                m_slRwLock.r2wLock();
                m_signalLock[key] = std::move(SignalLock());
                m_slRwLock.w2rLock();
            }
            SignalLock &t_signalLock = m_signalLock[key];
            m_slRwLock.unlock();
            t_signalLock.wait();
        } catch (std::exception ex) {
            ERR(ex.what());
            m_slRwLock.unlock();
            return false;
        }
        return true;
    }
    bool emitSigal(std::string key) {
        try {
            m_slRwLock.rdlock();
            if (m_signalLock.find(key) == m_signalLock.end()) {
                m_slRwLock.r2wLock();
                m_signalLock[key] = std::move(SignalLock());
                m_slRwLock.w2rLock();
            }
            SignalLock &t_signalLock = m_signalLock[key];
            m_slRwLock.unlock();
            t_signalLock.emit();
        } catch (std::exception ex) {
            ERR(ex.what());
            m_slRwLock.unlock();
            return false;
        }
        return true;
    }
};
#endif //GB28181SDK_GLOBALSIGNALWAITLOCK_H
QiaoJiaSystem/GB28181DecoderModel/SpinLock.hpp
New file
@@ -0,0 +1,30 @@
//
// Created by ps on 19-3-1.
//
#ifndef GB28181SDK_SPINLOCK_H
#define GB28181SDK_SPINLOCK_H
#include <atomic>
class SpinLock {
public:
    SpinLock() : m_lock(ATOMIC_FLAG_INIT) {}
    virtual ~SpinLock() {
    }
    void lock() {
        while (m_lock.test_and_set());
    }
    void unlock() {
        m_lock.clear();
    }
private:
    std::atomic_flag m_lock;
};
#endif //GB28181SDK_SPINLOCK_H
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp
New file
@@ -0,0 +1,210 @@
//
// Created by ps on 19-1-10.
//
#include <opencv2/imgproc.hpp>
#include <qt5/QtCore/QDateTime>
#include <basic/util/app/AppPreference.hpp>
#include "VideoCaptureElementWithRtp.h"
//std::string BASICGB28181::VideoCaptureElementWithRtp::m_chanPubID;
//BASICGB28181::FFmpegDecoderJPG BASICGB28181::VideoCaptureElementWithRtp::m_fFmpegDecoderJPG;
BASICGB28181::VideoCaptureElementWithRtp::VideoCaptureElementWithRtp(std::string &chanPubID, int fps,
                                                                     int streamTransType,
                                                                     int gpuIdx) : m_chanPubID(chanPubID), m_fps(fps),
                                                                                   m_running(false),
                                                                                   m_waitSignal(false),
                                                                                   m_streamTransType(streamTransType),
                                                                                   m_gpuIdx(gpuIdx),
                                                                                   m_userdata((long) this) {
//    m_chanPubID = chanPubID;
    m_cutPath = appPref.getStringData("user.loop.absolute.path");
    assert(!m_cutPath.empty());
}
BASICGB28181::VideoCaptureElementWithRtp::~VideoCaptureElementWithRtp() {
    m_fFmpegDecoderJPG.stopThd();
    int loop = 0;
    while ((loop++ < 100) && m_fFmpegDecoderJPG.getRunning()) {
        m_fFmpegDecoderJPG.stopThd();
        usleep(100000);
    }
}
bool BASICGB28181::VideoCaptureElementWithRtp::startRtpStream(int streamTransType) {
    TryCath(
    //--------------国标设备或则国标下级平台必须支持GB28181-2016----------------------------------------------
        std::thread videoCaptureElementThd([&](VideoCaptureElementWithRtp *p_this, int streamType) {
            DBG("videoCaptureElementThd start...");
            StreamTransType_E etype;
            switch (streamType) {
                case 1: {
                    // 1.实时视频请求 UDP请求实时视频
                    etype = E_STREAM_TRANS_UDP;
                    break;
                }
                case 2: {
                    // 2.实时视频请求 TCP主动请求实时视频
                    etype = E_STREAM_TRANS_TCPACTIVE;
                    break;
                }
                case 3: {
                    // 3.实时视频请求 TCP被动请求实时视频
                    etype = E_STREAM_TRANS_TCPPASSIVE;
                    break;
                }
                default:
                    etype = E_STREAM_TRANS_UDP;
            }
            DBG("C_RealVideoStart start... m_chanPubID is " << p_this->m_chanPubID << " etype is " << etype
                                                            << " m_userdata is " << m_userdata);
            long lrealhandle = C_RealVideoStart(const_cast<char *>(p_this->m_chanPubID.c_str()), etype,
                                                p_this->streamcallback, m_userdata);
            if (lrealhandle != -1) {
                DBG(p_this->m_chanPubID << "  C_RealVideoStart ok ... type is " << etype);
                p_this->m_running = true;
                p_this->m_fFmpegDecoderJPG.startThd(p_this->m_chanPubID, p_this->m_fps, p_this->m_gpuIdx);
                while (p_this->m_running) {
                    usleep(300000);
                }
                DBG("videoCaptureElementThd stop ...");
                C_RealVideoStop(lrealhandle);
                DBG("videoCaptureElementThd stop ok...");
            } else {
                p_this->m_running = false;
                p_this->m_fFmpegDecoderJPG.stopThd();
                ERR(p_this->m_chanPubID << " C_RealVideoStart is error lrealhandle is  " << lrealhandle);
            }
        }, this, streamTransType);
        videoCaptureElementThd.detach();
    );
    return true;
}
bool BASICGB28181::VideoCaptureElementWithRtp::stopRtpStream() {
    TryCath(
        m_running = false;
    );
    return true;
}
bool BASICGB28181::VideoCaptureElementWithRtp::getRunning() {
    return m_running;
}
void BASICGB28181::VideoCaptureElementWithRtp::streamcallback(long handle, int datatype, int frametype,
                                                              unsigned char *data, int datalen, long userdata) {
#ifdef TestCode
    ClockTimer test("streamcallback");
#endif
    BASICGB28181::VideoCaptureElementWithRtp *p_this = (BASICGB28181::VideoCaptureElementWithRtp *) userdata;
#ifdef TestCode
    {
//        FILE *fp11 = NULL;
//        if (!fp11) {
////            printf("fp11 handle:%ld, datatype:%d, datalen:%d, userdata:%ld\n", handle, datatype, datalen, userdata);
//            std::string fileName(p_this->m_chanPubID);
//            fileName.append(".mp4");
//            fp11 = fopen(fileName.c_str(), "w+");
//        }
//        fwrite(data, sizeof(char), datalen, fp11);
    }
#endif
    CHKDBG(p_this->m_fFmpegDecoderJPG.pushInfo(data, datalen, p_this->m_chanPubID), true,
           "pushInfo is error !! handle is " << handle << " datatype is " << datatype << " frametype is " << frametype);
}
void BASICGB28181::VideoCaptureElementWithRtp::threadFunc() {
    fireConnectors();
}
void BASICGB28181::VideoCaptureElementWithRtp::threadInitial() {
    std::thread waitSignalAndEmit([&](BASICGB28181::VideoCaptureElementWithRtp *p_this) {
        p_this->m_waitSignal = true;
        while (p_this->m_waitSignal) {
//#TODO wait test
#ifdef TestCode
            DBG("waitSignal(\"DecoderImageOK\") begin");
#endif
            gSignalLock.waitSignal(p_this->m_chanPubID + "DecoderImageOK");
#ifdef TestCode
            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_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(m_camId, imageName, copyMat);
            }
            p_this->submit();
        }
        INFO("waitSignalAndEmit is exit...");
    }, this);
    waitSignalAndEmit.detach();
    startRtpStream(m_streamTransType);
}
void BASICGB28181::VideoCaptureElementWithRtp::threadClosing() {
    m_waitSignal = false;
    stopRtpStream();
}
cv::Mat BASICGB28181::VideoCaptureElementWithRtp::getImage() {
    return m_image;
}
void BASICGB28181::VideoCaptureElementWithRtp::SetVideoMinMaxSeconds(const int minSeconds, const int maxSeconds) {
    m_fFmpegDecoderJPG.SetMinMaxVideoSeconds(minSeconds, maxSeconds);
}
void BASICGB28181::VideoCaptureElementWithRtp::SaveVideo(const std::string &strImageName) {
    INFO("SaveVideo: " << strImageName);
    std::string strTimeStamp = AppUtil::getTimeUSecString();
    std::string strPath = MakeDir(strTimeStamp);
    m_fFmpegDecoderJPG.SaveVideoByImageName(strPath, strImageName);
}
std::string BASICGB28181::VideoCaptureElementWithRtp::MakeDir(const std::string &timeStamp) {
    std::string t_FilePath = m_cutPath;
    if (t_FilePath.back() != '/') {
        t_FilePath.push_back('/');
    }
    char buf[24];
    QDateTime dt = QDateTime::fromString(QString::fromStdString(timeStamp), "yyyy-MM-dd hh:mm:ss:zzz");
    std::string t_strTime = dt.toString("yyyyMMddhh").toStdString();
    // DBG("t_strTime="<<t_strTime);
    t_FilePath.append(m_chanPubID + "/" + t_strTime.substr(0, 6) + "/" + t_strTime.substr(6, 2) + "/");
    //YYYYMMDDHH
    t_FilePath.append(t_strTime.substr(0, 10) + "/");
    std::string t_cmd = "mkdir -p '";
    t_cmd.append(t_FilePath + "'");
    //#get path mkdir path
    system(t_cmd.c_str());
    return t_FilePath;
}
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h
New file
@@ -0,0 +1,94 @@
//
// Created by ps on 19-1-10.
//
#ifndef GB28181SDK_VIDEOCAPTUREELEMENT_H
#define GB28181SDK_VIDEOCAPTUREELEMENT_H
#include "FFmpegDecoderJPG.h"
#include "28181SDK.h"
#include <basic/pipe/PipeElement.h>
#include "GlobalSignalWaitLock.hpp"
namespace BASICGB28181 {
    class VideoCaptureElementWithRtp : public basic::PipeElement {
    public:
        explicit VideoCaptureElementWithRtp(std::string &chanPubID, int fps, int streamTransType, int gpuIdx = -1);
        virtual ~VideoCaptureElementWithRtp();
        /***
         * 获取当前实时流接收数据线程运行状态
         * @return
         */
        bool getRunning();
        cv::Mat getImage();
        //保存视频接口,从RtspAnalysManager发起调用
        void SaveVideo(const std::string &strImageName);
        //设置保存视频的最小和最大长度,单位是秒,实际的运行情况有一些差距,需要完善
        void SetVideoMinMaxSeconds(const int minSeconds, const int maxSeconds);
        //根据timeStamp创建路径
        std::string MakeDir(const std::string &timeStamp);
    private:
        int m_gpuIdx;
        int m_fps;
        int m_streamTransType;
        std::string m_chanPubID;
        std::atomic<int> m_picCount{0};
        //几张图丢一张,目前是8张丢一张
        const int m_nPicsPickOne = 8;
        FFmpegDecoderJPG m_fFmpegDecoderJPG;
        cv::Mat m_image;
        long m_userdata;
        std::atomic<bool> m_running;
        std::atomic<bool> m_waitSignal;
        //用来保存录像视频的路径
        std::string m_cutPath;
    private:
        /***
         * 启动实时流接收数据线程
         * @param streamTransType 流数据发送方式
         * @return
         */
        bool startRtpStream(int streamTransType = 1);
        /***
         * 停止实时流接收数据线程
         * @return
         */
        bool stopRtpStream();
        /***
         * rtp组包回调函数
         * @param handle
         * @param datatype
         * @param frametype
         * @param data
         * @param datalen
         * @param userdata
         */
        static void streamcallback(long handle, int datatype, int frametype,
                                   unsigned char *data, int datalen, long userdata);
        virtual void threadFunc() override;
        virtual void threadInitial() override;
        virtual void threadClosing() override;
    };
}
#endif //GB28181SDK_VIDEOCAPTUREELEMENT_H
QiaoJiaSystem/GB28181DecoderModel/main.cpp
New file
@@ -0,0 +1,123 @@
//
// Created by ps on 19-1-8.
//
#include <iostream>
#include <thread>
#include <Debug.h>
#include "GB28181Server.h"
#include "VideoCaptureElementWithRtp.h"
#include <opencv2/opencv.hpp>
#include <CvUtil.h>
using namespace std;
int main(int argc, char **argv) {
    std::cout << "test " << std::endl;
    bool running = true;
    bool serinit = false;
    MysqlDBServerCfg mysqlDBServerCfg;
    mysqlDBServerCfg.Host = "192.168.1.148";
    mysqlDBServerCfg.Port = 3306;
    mysqlDBServerCfg.UserName = "root";
    mysqlDBServerCfg.Passwd = "123456";
    mysqlDBServerCfg.DBName = "EGEyesForVSS";
    mysqlDBServerCfg.DBConnCount = 5;
    GBServerCfg gbServerCfg;
    gbServerCfg.SvrIp = "192.168.1.148"; // 国标服务的ip地址  (本机的ip地址)
    gbServerCfg.SvrPort = 7060; // 国标服务监听的端口
    gbServerCfg.SvrPubID = "44120000002000000001"; // 国标服务器的ID
    gbServerCfg.bMD5Auth = false; // 是否需要MD5加密
    gbServerCfg.UserName = "44120100002000000002"; // 国标服务的用户名    (下级设备注册的用户名)
    gbServerCfg.Passwd = "123456"; // 国标服务的密码    (下级设备注册的密码)
    gbServerCfg.SubScribeTime = 3600; // 订阅时间  如果为0 表示不订阅
    SpinLock spinLock;
    auto func = [&] {
        spinLock.lock();
        GB28181Server m_gbs;
        m_gbs.setMysqlConnParam(mysqlDBServerCfg);
        m_gbs.setGBServerParam(gbServerCfg);
        DBG("initServer start before");
        serinit = m_gbs.initServer();
        DBG("initServer start after");
        spinLock.unlock();
        while (running) {
            usleep(4000);
        }
    };
    std::thread thd(func);
    //      ---------------------测试------------------------
    spinLock.lock();
    DBG("test start");
    //#todo search from db
    char ChanPubID2[] = "11010202081314000001";
    std::string str_ChanPubID2(ChanPubID2);
    BASICGB28181::VideoCaptureElementWithRtp videoCapture2(str_ChanPubID2, 25, 1, 0);
    videoCapture2.registerConnector([&]() {
        {
            //testCode
            cv::Mat t_image = videoCapture2.getImage();
            if (t_image.empty()) {
                ERR("t_image is empty");
                return;
            }
            std::string strNewTime;
            strNewTime = AppUtil::getTimeUSecString();
            cv::putText(t_image, strNewTime, cv::Point(408, 540), cv::HersheyFonts::FONT_HERSHEY_PLAIN, 5,
                        cv::Scalar(255, 255, 0), 2);
            DBG("imshow image" << str_ChanPubID2 << strNewTime);
//            imshow("str_ChanPubID2", t_image);
//            cv::waitKey(10);
#if 1
            {
//            TestCode
//                ClockTimer cl("str_ChanPubID1");
                std::string strNewTime2 = AppUtil::getTimeUSecString();
//                cv::putText(t_image, strNewTime2, cv::Point(408, 540), cv::HersheyFonts::FONT_HERSHEY_PLAIN,
//                            5, cv::Scalar(255, 255, 0), 2);
                std::thread test([&](cv::Mat img, std::string strThing) {
                    try {
                        std::string strNewTime = "tmpDec/";
                        strNewTime.append(str_ChanPubID2 + "_").append(strThing).append(".jpg");
                        cv::imwrite(strNewTime, img);
                    } catch (std::exception ex) {
                        ERR(ex.what());
                    }
                }, t_image, strNewTime2);
                test.detach();
            }
#endif
        }
    });
    usleep(10);
    videoCapture2.start();
    sleep(60);
    videoCapture2.stop();
    DBG("test end");
    getchar();
    running = false;
    getchar();
    sleep(2);
    return 0;
}
QiaoJiaSystem/LocalDBTool/SqliteFaceEncap.cpp
@@ -179,6 +179,9 @@
        if (faceData.faceUrl.size() > 0) {
            strSql.append(" faceUrl =  :faceUrl ,");
        }
//        if (faceData.enabled.size() > 0) {
//            strSql.append(" enabled =  :enabled ,");
//        }
        //#todo
        strSql.append(" update_time = '2010-01-03 01:01:00' ");
@@ -192,6 +195,9 @@
        if (faceData.faceUrl.size() > 0) {
            query.addBindValue(QString::fromStdString(faceData.faceUrl));
        }
//        if (faceData.enabled.size() > 0) {
//            query.addBindValue(QString::fromStdString(faceData.enabled));
//        }
        if (!query.exec()) {
            ERR("updateFaceData fail");
@@ -370,6 +376,11 @@
            tableInfo.bwType = query.value(3).toString().toStdString();
            tableInfo.startTime = query.value(4).toString().toStdString();
            tableInfo.endTime = query.value(5).toString().toStdString();
            tableInfo.uploadFlag = query.value(6).toString().toStdString();
            tableInfo.cmpThreshold = query.value(7).toString().toStdString();
            tableInfo.enabled = query.value(8).toString().toStdString();
            tableInfo.createBy = query.value(9).toString().toStdString();
            tableInfos.push_back(tableInfo);
        }
    }
@@ -397,6 +408,8 @@
            tableInfo.sex = query.value(3).toString().toStdString();
            tableInfo.idCard = query.value(4).toString().toStdString();
            tableInfo.phoneNum = query.value(5).toString().toStdString();
            tableInfo.enable = query.value(10).toString().toStdString();
            tableInfo.monLevel = query.value(11).toString().toStdString();
            faceInfosCache.insert(std::make_pair(tableInfo.uuid, tableInfo));
        }
    }
QiaoJiaSystem/LocalDBTool/SqliteFaceEncap.h
@@ -12,15 +12,35 @@
/**
 * #todo sqlite -> Qt.sqlite
 */
/***
 * sqlite3 操作工具类
 */
class SqliteFaceEncap : public sqliteEncapsulation {
public:
    explicit SqliteFaceEncap(std::string t_string);
    /***
     * 创建布控底库
     * 不通用,因为内部有一个insert函数调用
     * @param t_tableName
     * @param fieldValues
     * @return
     */
    bool createTable(std::string t_tableName, FieldValues &fieldValues);
    /***
     * 通用的单表更新
     * @param t_tableName
     * @param fieldValues
     * @return
     */
    bool updateTable(std::string t_tableName, FieldValues &fieldValues);
    /***
     * 删除表
     * @param t_tableName
     * @return
     */
    bool deleteTable(std::string t_tableName);
    /***
@@ -30,26 +50,80 @@
     */
    std::vector<std::string> getTableNameList(std::string type);
    /***
     * 获取所有已创建的表信息
     * @return
     */
    TableInfos getTableInfos();
public:
    /***
     * 添加人脸
     * @param t_tableName 表名
     * @param faceData 人脸特征结构体
     * @param fieldValues 字段集合
     * @return
     */
    std::string addFace(std::string t_tableName, AddFaceData &faceData, FieldValues &fieldValues);
    /***
     * 更新人脸
     * @param t_tableName 表名
     * @param faceData 人脸特征结构体
     * @param fieldValues 字段集合
     * @return
     */
    bool updateFace(std::string t_tableName, AddFaceData &faceData, FieldValues &fieldValues);
    /***
     * 向人脸特征表插入记录
     * @param t_tableName
     * @param faceData
     * @return
     */
    std::string addFaceData(std::string t_tableName, AddFaceData &faceData);
    //#todo
    /***
     * 添加人脸业务信息
     * @param t_tableName
     * @param fieldValues
     * @return
     */
    bool addFaceInfo(std::string t_tableName, FieldValues &fieldValues);
    /***
     *
     * @param t_tableName
     * @param faceData
     * @return
     */
    bool updateFaceData(std::string t_tableName, AddFaceData &faceData);
    /***
     *
     * @param t_tableName
     * @param fieldValues
     * @return
     */
    bool updateFaceInfo(std::string t_tableName, FieldValues &fieldValues);
    /***
     *
     * @param t_tableName
     * @param uuid
     * @return
     */
    bool deleteFace(std::string t_tableName, std::string uuid);
private:
    /***
     *
     * @param t_tableName
     * @param uuid
     * @return
     */
    bool deleteFaceData(std::string t_tableName, std::string uuid);
public:
QiaoJiaSystem/LocalDBTool/SqliteToolkit.hpp
@@ -1,6 +1,10 @@
//
// Created by pans on 4/28/18.
//
/***
 * 说明,本文件主要是sql语句拼接及获取已定义的sql语句
 * 目前仅支持单表sql语句拼接
 */
#ifndef TESTSQLITE_SQLITETOOLKIT_HPP
#define TESTSQLITE_SQLITETOOLKIT_HPP
@@ -24,12 +28,19 @@
 */
typedef std::vector<unsigned char> FaceFeature;
/***
 * 添加人脸的数据结构
 */
struct AddFaceData {
    std::string uuid;
    FaceFeature feature;
    std::string faceUrl;
    std::string feature_base64;
};
/***
 * 人脸信息的数据结构
 */
struct FaceInfo {
    std::string uuid;
    std::string personName;
@@ -37,10 +48,15 @@
    std::string sex;
    std::string idCard;
    std::string phoneNum;
    std::string enable;
    std::string monLevel;
};
typedef std::vector<FaceInfo> FaceInfos;
typedef std::map<std::string, FaceInfo> FaceInfosCache;
/***
 * 表信息数据结构
 */
struct TableInfo {
    std::string uuid;
    std::string tableName;
@@ -49,6 +65,10 @@
    std::string startTime;
    std::string endTime;
    std::string createBy;
    std::string uploadFlag;
    std::string cmpThreshold;
    std::string enabled;
};
typedef std::vector<TableInfo> TableInfos;
typedef std::map<std::string, TableInfo> TableInfosCache;
@@ -57,10 +77,15 @@
//typedef std::map<std::string, FaceFeatures> FeatureDBCache;
/***
 * 带有URL和其他属性的人脸特征数据结构
 */
struct FaceFeatureWithUrl {
    std::string uuid;
    std::string faceurl;
    FaceFeature faceFeature;
    std::string enable;
    std::string monLevel;
};
typedef std::map<std::string, FaceFeatureWithUrl> FeatureDBWithUrlCache;
@@ -72,39 +97,59 @@
#define SQLERR(message) fprintf(stderr, "%s->%d->  SQLite error: %s\n",__FILE__,__LINE__, message);
    //#todo 数据库wenjian名称
    //#todo 数据库文件名称
    //是否需要从配置文件读取?
    static std::string file_dbName = "TestFaceDB.db";
    //#todo 数据库名称
    static std::string g_dbName = "main";
    //#todo 管理表的表名
    static std::string g_tableName = "sys_o_tables";
    //
    /***
     * 获取人脸特征查询的sqlite语句
     * @param tableName 表名,不带 _fea
     * @return
     */
    std::string getFacesFromTableSql(std::string tableName) {
//        #todo get monLevel 联合查询
        std::string sql =
            "select uuid,feature,create_time,faceUrl,del_flag from " + tableName +
            "_fea where feature is not null ";
            "select uuid,feature,create_time,faceUrl,del_flag from '" + tableName +
            "_fea' where feature is not null ";
        return sql;
    }
    /***
     * 根据表类型获取数据表列表
     * @param type
     * @return
     */
    std::string getTableListSqlWithType(std::string type) {
        std::string sql = "select tableName,del_flag from " + g_tableName + " where del_flag = 0";
        std::string sql = "select tableName,del_flag from '" + g_tableName + "' where del_flag = 0";
        if (type.size() > 0) {
            sql.append(" and tableType = '" + type + "'");
        }
        return sql;
    }
    /***
     * 查询任意表的所有字段
     * @param tableName
     * @return
     */
    std::string getTableInfosSql(std::string tableName) {
        std::string sql = "select * from " + tableName;// + " where del_flag = 0";
        std::string sql = "select * from '" + tableName + "';";// + " where del_flag = 0";
        return sql;
    }
    /***
     * 获取当前已创建的表
     * @return
     */
    std::string getTableInfosSql() {
        //uuid,tableName,tableDesc,tableType,bwType,startTime,endTime
        std::string sql = "select uuid,tableName,tableType,bwType,startTime,endTime from " + g_tableName +
                          " where del_flag = 0";
        std::string sql =
            "select uuid,tableName,tableType,bwType,startTime,endTime,uploadFlag,cmpThreshold,enabled,create_by from " +
            g_tableName + " where del_flag = 0";
        return sql;
    }
@@ -124,7 +169,7 @@
        str_fea.assign(feature.begin(), feature.end());
        std::stringstream sql;//= ;
        sql << "INSERT INTO " << tableName << " (";
        sql << "INSERT INTO '" << tableName << "' (";
        //std::string sqlTemp = sql;
        std::string sql2 = ") VALUES(\"";
        if (id >= 0) {
@@ -149,7 +194,7 @@
            //#todo errInfo
            return "tableName or fieldValues is NULL";
        }
        std::string sql = "DELETE from " + tableName + " where 1 = 1 ";
        std::string sql = "DELETE from '" + tableName + "' where 1 = 1 ";
        for (auto item : fieldValues) {
            if (item.first.size() != 0) {
                sql.append("and " + item.first + " = '" + item.second + "' ");
@@ -169,11 +214,11 @@
            //#todo errInfo
            return "tableName or fieldValues is NULL";
        }
        std::string sql = "INSERT INTO " + tableName + " (";
        std::string sql = "INSERT INTO '" + tableName + "' (";
        std::string sqlTemp = sql;
        std::string sql2 = ") VALUES('";
        for (auto item : fieldValues) {
            if (item.first.size() != 0) {
            if (item.first.size() != 0 && item.second.size() != 0) {
                sql.append(item.first + ",");
                sql2.append(item.second + "','");
            }
@@ -182,7 +227,7 @@
        sql = sql.substr(0, sql.length() - 1);
        //sql2 delete 2 ,'  add )
        sql2 = sql2.substr(0, sql2.length() - 2);
        sql2.append(" )");
        sql2.append(" );");
        sql.append(sql2);
        return sql;
    }
@@ -193,6 +238,9 @@
     * @return sql
     */
    std::string getInitDBSql() {
//        %%      ALTER TABLE sys_o_tables ADD COLUMN uploadFlag varchar(255) DEFAULT 0;
//        %%      ALTER TABLE sys_o_tables ADD COLUMN cmpThreshold varchar(255) DEFAULT 60;
//        %%      ALTER TABLE sys_o_tables ADD COLUMN enabled varchar(255) DEFAULT 1;
        std::string sql = "CREATE TABLE \"main\".\"sys_o_tables\" (";
        sql.append(" uuid        varchar(255) PRIMARY KEY, ");
//        sql.append(" ClusterName varchar(255) DEFAULT NULL,");//本地库不需要
@@ -205,7 +253,10 @@
        sql.append(" create_time BLOB default (datetime('now', 'localtime')),");
        sql.append(" update_time varchar(255) DEFAULT NULL,");
        sql.append(" create_by   varchar(255) DEFAULT NULL,");
        sql.append(" del_flag    varchar(255) DEFAULT 0");
        sql.append(" del_flag    varchar(255) DEFAULT 0,");
        sql.append(" uploadFlag  varchar(255) DEFAULT 0,");
        sql.append(" cmpThreshold    varchar(255) DEFAULT 60,");
        sql.append(" enabled     varchar(255) DEFAULT 1");
        sql.append(");");
        return sql;
    }
@@ -222,9 +273,9 @@
            return "tableName is NULL";
        }
        // 人员信息表
        std::string sql = "CREATE TABLE " + g_dbName + ".";
        std::string sql = "CREATE TABLE " + g_dbName + ".'";
        sql.append(tableName);
        sql.append(" (  uuid        varchar(255) PRIMARY KEY,");
        sql.append("' (  uuid        varchar(255) PRIMARY KEY,");
        sql.append("personName  varchar(255) DEFAULT NULL,");
        sql.append("age         varchar(255) DEFAULT NULL,");
        sql.append("sex         varchar(255) DEFAULT NULL,");
@@ -233,11 +284,13 @@
        sql.append("create_time BLOB         DEFAULT (datetime('now', 'localtime')),");
        sql.append("update_time DATETIME     DEFAULT NULL,");
        sql.append("create_by   varchar(255) DEFAULT NULL,");
        sql.append("del_flag    INTEGER      DEFAULT 0");
        sql.append("del_flag    INTEGER      DEFAULT 0,");
        sql.append("monitorLevel    varchar(255)      DEFAULT 0,");
        sql.append("    enabled     varchar(255) DEFAULT 1");
        sql.append(");");
        // 人脸特征表
        sql.append("CREATE TABLE " + g_dbName + ".");
        sql.append(tableName + "_fea");
        sql.append("CREATE TABLE " + g_dbName + ".'");
        sql.append(tableName + "_fea'");
        sql.append(" (  uuid        varchar(255) PRIMARY KEY,");
        sql.append("    feature     BLOB NOT NULL,");
        sql.append("    faceUrl     BLOB NOT NULL,");
@@ -249,7 +302,12 @@
        return sql;
    }
    /***
     * 获取更新人脸业务信息表的sql语句
     * @param tableName
     * @param fieldValues
     * @return
     */
    std::string getUpdateFaceTableSql(std::string tableName, FieldValues &fieldValues) {
        if (tableName.size() == 0) {
            //#todo errInfo
@@ -265,25 +323,33 @@
            SQLERR("fieldValues size is error");
            return "";
        }
        std::string sql = "update ";
        sql.append(tableName + " set ");
        std::string sql = "update '";
        sql.append(tableName + "' set ");
        for (auto &item :fieldValues) {
            if (item.second.size() == 0) {
                continue;
            }
            sql.append(item.first + " =  '" + item.second + "',");
        }
        sql.append(" update_time ='" + AppUtil::getTimeSecString() + "'");
        sql.append(" where uuid ='" + uuid + "'");
        sql.append(" where uuid ='" + uuid + "';");
        return sql;
    }
    //#TODO 人脸表需要删除两个
    /***
     * 获取删除人脸表的sql语句
     * @param tableName
     * @return
     */
    std::string getDeleteFaceTableSql(std::string tableName) {
        if (tableName.size() == 0) {
            //#todo errInfo
            return "tableName is NULL";
        }
        std::string sql = "DROP TABLE " + g_dbName + "." + tableName + ";";
        sql.append("DROP TABLE " + g_dbName + "." + tableName + "_fea;");
        std::string sql = "DROP TABLE " + g_dbName + ".'" + tableName + "';";
        sql.append("DROP TABLE " + g_dbName + ".'" + tableName + "_fea';");
        return sql;
    }
QiaoJiaSystem/VideoToImageMulth/RtspAnalysManager.cpp
@@ -10,11 +10,10 @@
RtspAnalysManager::RtspAnalysManager(LDBTool *_dbTool) : m_lDBTool(nullptr), m_maxCount(50), m_currentCount(0) {
    INFO("MYH DEBUG HERE");
    m_lDBTool=new LDBTool;
    m_lDBTool = new LDBTool;
    init();
}
static std::string rtspAddrBuild(std::string ip, const int port, std::string username,
@@ -50,27 +49,25 @@
    if (lst.size() > 0) {
        int startCamNO = appPref.getIntData("CamStart") * appPref.getIntData("CamStep");
        int CamCount = appPref.getIntData("CamStep");
        INFO("StartCamNO: "<<startCamNO<<" CamStep: "<<CamCount);
        INFO("StartCamNO: " << startCamNO << " CamStep: " << CamCount);
        auto itor = lst.begin();
        if(startCamNO >= lst.size())
        {
        if (startCamNO >= lst.size()) {
            ERR("startCamNO > lst.size()");
            return;
        }
        for(int i=0; i < startCamNO; i++){
        for (int i = 0; i < startCamNO; i++) {
            std::string t_camIdex = itor->str_cam_dev_id.toStdString();
            std::string rtsp_url = rtspAddrBuild(itor->str_ip.toStdString(), 554, itor->str_username.toStdString(),
                                                 itor->str_password.toStdString(), itor->str_brand.toStdString());
            INFO("JumpCam: "<<t_camIdex<<"  URL: "<<rtsp_url);
            INFO("JumpCam: " << t_camIdex << "  URL: " << rtsp_url);
            itor++;
        }
        for (int i = 0; i < CamCount; i++) {
            if (itor == lst.end())
            {
            if (itor == lst.end()) {
                ERR("itor == lst.end()");
                return;
            }
@@ -102,7 +99,7 @@
RtspAnalysManager::~RtspAnalysManager() {
    INFO("Program Exit");
    for (auto controller: m_controllers) {
        INFO("Delete Controller: "<<controller.first);
        INFO("Delete Controller: " << controller.first);
        delete controller.second;
    }
    m_controllers.clear();
@@ -116,7 +113,7 @@
 * @param rtsp 上面的摄像机对应的视频路径
 * @return -1 添加失败,0 添加成功
 */
int RtspAnalysManager::addCamera(const std::string &index, const std::string& rtsp) {
int RtspAnalysManager::addCamera(const std::string &index, const std::string &rtsp) {
    auto lst = m_lDBTool->searchCamDevTableAll();
    Record_Config lst_dev = m_lDBTool->searchConfigTableWithinServerInfo();
@@ -126,13 +123,13 @@
            ERR("addCamera faild, camera's num is full!")
            return -1;
        }
        INFO("RTSP: "<<rtsp<<"  INDEX:"<<index);
        INFO("RTSP: " << rtsp << "  INDEX:" << index);
        m_imgRedisControllers[index] = new RtspImageRedisElement(index);
        m_imgRedisControllers[index]->start();
        m_controllers[index] = new RtspCaptureElement(rtsp,index, 25,3000,0,this);
        m_controllers[index] = new RtspCaptureElement(rtsp, index, 25, 3000, 0, this);
        m_controllers[index]->start();
        m_controllers[index]->SetVideoMinMaxSeconds(lst_dev.n_cut_min_duration,lst_dev.n_cut_max_duration);
        m_controllers[index]->SetVideoMinMaxSeconds(lst_dev.n_cut_min_duration, lst_dev.n_cut_max_duration);
        m_currentCount++;
        return 0;
@@ -212,37 +209,31 @@
//录取视频的RPC的接口函数
::std::string RtspAnalysManager::recordVideo(const ::std::string& name, const ::Ice::Current&)
{
    INFO("Record Video For: "<<name);
    ImageName_s_t nameSt=ImageName_s_t::fromString(name);
    if(nameSt.Valid())
    {
::std::string RtspAnalysManager::recordVideo(const ::std::string &name, const ::Ice::Current &) {
    INFO("Record Video For: " << name);
    ImageName_s_t nameSt = ImageName_s_t::fromString(name);
    if (nameSt.Valid()) {
        auto pCaptureElem = m_controllers.find(nameSt.m_camId);
        if(pCaptureElem!= m_controllers.end())
        {
        if (pCaptureElem != m_controllers.end()) {
            pCaptureElem->second->SaveVideo(name);
        } else{
            ERR("Can not Find CamId "<<nameSt.m_camId);
        } else {
            ERR("Can not Find CamId " << nameSt.m_camId);
        }
    }
    else{
        ERR("Record Video Failed:Name Not Valid  Name:  "<<name);
    } else {
        ERR("Record Video Failed:Name Not Valid  Name:  " << name);
    }
    return name;
}
//保存视频到RtspImageRedis的队列,由RtspCaptureElement调用
bool RtspAnalysManager::SaveImageToRedis(const std::string& camId,const std::string& imageName,const cv::Mat& img)
{
bool RtspAnalysManager::SaveImageToRedis(const std::string &camId, const std::string &imageName, const cv::Mat &img) {
    INFO("MYH DEBUG HERE");
    auto item = m_imgRedisControllers.find(camId);
    if(item!=m_imgRedisControllers.end())
    {
        INFO("Save Succeed Cam: "<<camId<<" ImageKey: "<<imageName);
        item->second->SaveImage(imageName,img);
    if (item != m_imgRedisControllers.end()) {
        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);
    }
    INFO("MYH DEBUG HERE");
    return true;
QiaoJiaSystem/VideoToImageMulth/RtspCaptureElement.h
@@ -41,7 +41,7 @@
        std::string m_path;
        // Redis的工具类
        HiredisTool m_redisTool;
//        HiredisTool m_redisTool;
        //对保存到Redis的图片进行计数
        std::atomic<int> m_picCount{0};
QiaoJiaSystem/VideoToImageMulth/RtspImageRedis.h
@@ -47,7 +47,7 @@
    std::string m_camId;
    //每台摄像机保存到Redis的图片数量的最大值
    const int M_CAM_PIC_MAX_COUNT = 25;
    const int M_CAM_PIC_MAX_COUNT = 3;
};
#endif // VIDEOCAPTUREELEMENT_H
QiaoJiaSystem/YoloServer/main.cpp
@@ -30,12 +30,12 @@
//        return -1;
//    }
    int gpuindex = 1;
    int gpuindex = 0;
    int poolNum = 1;
    int portNum = 10003;
    appPref.setIntData("gpu.index", gpuindex);
    appPref.setFloatData("thresh.detect", 0.7);
    appPref.setFloatData("thresh.detect", 0.85);
    appPref.setIntData("poolNum", poolNum);
    IceRpcServer<YoloDetectServerI> server("yoloServer", portNum, "tcp");
syncDBTool/ErlangDbTool.cpp
@@ -639,6 +639,14 @@
    return false;
}
bool ErlangTool::ErlangDbTool::createDatabase(std::string t_tableName, FieldValues &fieldValues) {
//    #todo 记得测试中文
    std::string strSql = getCreateFaceTableSql(t_tableName);
    strSql.append(getInsertSql("sys_o_tables", fieldValues));
    getExecSqlResult(strSql);
}
bool ErlangTool::ErlangDbTool::updateDatabase(std::string UUID, std::string TableType, std::string TableName,
                                              bool SyncType, std::string BwType, std::string StartTime,
                                              std::string EndTime) {
@@ -722,6 +730,86 @@
    return false;
}
bool ErlangTool::ErlangDbTool::updateDatabase(std::string t_tableName, FieldValues &fieldValues) {
    //    #todo 记得测试中文
    std::string strSql = getUpdateFaceTableSql(t_tableName, fieldValues);
    return getExecSqlResult(strSql);
}
bool ErlangTool::ErlangDbTool::getExecSqlResult(const std::string &strSql) {
    ErlangTool::LockG lock(m_mutex);
//            m_mutex.lock();
    m_ret = resetConn();
    if (!m_ret) {
        //#todo error message
        std::cout << __FILE__ << __FUNCTION__ << __LINE__ << " error " << this->m_ret << "  " << this->m_fd
                  << std::endl;
        return false;
    }
    ErlMessage emsg;             /* Incoming message */
    int ret = -1;
    ETERM *arrlist[7];
    arrlist[0] = erl_mk_string(strSql.c_str());
    ETERM *list = erl_mk_list(arrlist, 1);
    ret = erl_rpc_to(m_fd, "syncDB", "exeSomeSql", list);
    if (ret == ERL_TICK) {
        ret = erl_rpc_from(m_fd, TIMEOUT, &emsg);
        //erl_close_connection(m_fd);
//                m_mutex.unlock();
        if (ret == ERL_MSG) {
            std::map<std::__cxx11::string, std::__cxx11::string> t_results;
            ETERM *tail_list;
            ETERM *list_ret[1000], *arr_ret[2];
            ETERM *key, *value;
            ETERM *tuplep[6];
            arr_ret[0] = erl_element(2, emsg.msg);
            int erlLength = erl_length(arr_ret[0]);
            printf("arr_ret[0]:%d\n", erlLength);
            list_ret[0] = erl_hd(arr_ret[0]);
            tail_list = erl_tl(arr_ret[0]);
            for (int i = 0; i < erlLength; i++) {
                if (i > 0) {
                    list_ret[i] = erl_hd(tail_list);
                    tail_list = erl_tl(tail_list);
                }
//                    printf("list_ret[%d]:%d\n", i, erl_length(list_ret[i]));
                tuplep[0] = erl_hd(list_ret[i]);
                key = erl_element(1, list_ret[i]);
                value = erl_element(2, list_ret[i]);
//                    printf("key:%s\n", ERL_ATOM_PTR(key));
                switch (ErlangTool::checkETERMType(value)) {
                    case ERL_ATOM: {
//                            int atomSize = ERL_ATOM_SIZE(value);
                        char *atomValue = ERL_ATOM_PTR(value);
//                            printf("value is a atom: atomSize:%d, atomValue:%s \n\r", atomSize, atomValue);
                        t_results.insert(std::make_pair(ERL_ATOM_PTR(key), atomValue));
                        break;
                    }
                    default:
                        printf("error add case todo \n\r");
                }
                ErlangTool::erlangFreeEterm(4, key, value, tuplep[0], list_ret[i]);
            }
            ErlangTool::erlangFreeEterm(2, tail_list, arr_ret[0]);
            erl_eterm_release();
            auto it = t_results.find("atomic");
            if (t_results.size() > 0 && t_results.end() != it && it->second == "ok") {
                return true;
            }
        }
    }
    erl_free_array(arrlist, 1);
//            erlangFreeEterm(4, emsg.to, emsg.msg, emsg.from, list);
    erl_eterm_release();
    return false;
}
bool ErlangTool::ErlangDbTool::deleteDatabase(std::string TableType, std::string TableName, bool SyncType) {
    LockG lock(m_mutex);
//            m_mutex.lock();
@@ -791,6 +879,19 @@
    erl_free_array(arrlist, 2);
    erlangFreeEterm(4, emsg.to, emsg.msg, emsg.from, list);
    return false;
}
bool ErlangTool::ErlangDbTool::deleteDatabase(std::string t_tableName) {
    FieldValues fieldValues;
    fieldValues.insert(std::make_pair("uuid", t_tableName));
    fieldValues.insert(std::make_pair("del_flag", "1"));
    std::string strSql = getUpdateFaceTableSql("sys_o_tables", fieldValues);
    strSql.append("DROP TABLE '" + t_tableName + "';DROP TABLE '" + t_tableName + "_fea';");
    //    #todo 记得测试中文
    return getExecSqlResult(strSql);
}
// 和erlang交互
@@ -894,7 +995,7 @@
    map_TabDataCache tabDataCache;
    QString sql = QString::fromStdString(
        "SELECT  uuid,tableName,tableType,bwType,startTime,endTime FROM sys_o_tables where del_flag=0;");
        "SELECT  uuid,tableName,tableType,bwType,startTime,endTime,uploadFlag,cmpThreshold,enabled,create_by FROM sys_o_tables where del_flag=0;");
    QSqlQuery query(g_syncDbFile);
    query.prepare(sql);
    if (!query.exec()) {
@@ -908,6 +1009,10 @@
            t_table_info.bwType = query.value(3).toString().toStdString();
            t_table_info.startTime = query.value(4).toString().toStdString();
            t_table_info.endTime = query.value(5).toString().toStdString();
            t_table_info.uploadFlag = query.value(6).toString().toStdString();
            t_table_info.cmpThreshold = query.value(7).toString().toStdString();
            t_table_info.enabled = query.value(8).toString().toStdString();
            t_table_info.create_by = query.value(9).toString().toStdString();
            tabDataCache.insert(std::make_pair(t_table_info.uuid, t_table_info));
        }
@@ -1080,6 +1185,35 @@
    return false;
}
bool ErlangTool::ErlangDbTool::addPerson(std::string t_tableName, AddFaceData &faceData, FieldValues &fieldValues) {
//    #todo 记得测试中文
    std::string strSql = getInsertSql(t_tableName, fieldValues);
    fieldValues.clear();
    fieldValues.insert(make_pair("uuid", faceData.uuid));
    fieldValues.insert(make_pair("faceUrl", faceData.faceUrl));
    fieldValues.insert(make_pair("feature", faceData.feature_base64));
    std::string strSqlFea = getInsertSql(t_tableName + "_fea", fieldValues);
    strSql.append(strSqlFea);
    //    #todo 记得测试中文  只有人员信息表更新,特征更新暂时没做
    return getExecSqlResult(strSql);
}
bool ErlangTool::ErlangDbTool::updatePerson(std::string t_tableName, AddFaceData &faceData, FieldValues &fieldValues) {
//    #todo 记得测试中文
    std::string strSql = getUpdateFaceTableSql(t_tableName, fieldValues);
    fieldValues.clear();
    fieldValues.insert(make_pair("uuid", faceData.uuid));
    fieldValues.insert(make_pair("faceUrl", faceData.faceUrl));
    fieldValues.insert(make_pair("feature", faceData.feature_base64));
    std::string strSqlFea = getInsertSql(t_tableName + "_fea", fieldValues);
    strSql.append(strSqlFea);
    return getExecSqlResult(strSql);
}
ErlangTool::vec_AddDataCache
ErlangTool::ErlangDbTool::addPersons(std::string TableUuid, std::vector<SyncDB::AddPersonInfo> &tmpPer) {
@@ -1480,7 +1614,8 @@
    }
    if (str_tableUuid.size() > 0) {
        QString sql = QString::fromStdString(
            "Select a.uuid as id ,a.faceUrl as img,a.feature,b.idCard as idcard from '" + str_tableUuid +
            "Select a.uuid as id ,a.faceUrl as img,a.feature,b.idCard as idcard,b.enable,b.monitorLevel from '" +
            str_tableUuid +
            "_fea' as a ,'" + str_tableUuid + "' as b  where a.uuid = b.uuid and ( a.del_flag=0 AND b.del_flag=0);");
        QSqlQuery query(g_syncDbFile);
        query.prepare(sql);
@@ -1493,6 +1628,8 @@
                t_feature_info.img = query.value(1).toString().toStdString();
                t_feature_info.feature = query.value(2).toString().toStdString();
                t_feature_info.idcard = query.value(3).toString().toStdString();
                t_feature_info.enable = query.value(4).toString().toStdString();
                t_feature_info.monLevel = query.value(5).toString().toStdString();
                dataCache.insert(std::make_pair(t_feature_info.id, t_feature_info));
            }
@@ -1517,9 +1654,12 @@
        }
    }
    if (str_tableUuid.size() > 0) {
//        QString sql = QString::fromStdString(
//            "Select b.uuid as id,b.faceUrl as img,a.idCard as idcard,a.enable,a.monitorLevel from '" + str_tableUuid +
//            "' as a, '" + str_tableUuid + "_fea' As b  where a.uuid = b.uuid and ( a.del_flag=0 AND b.del_flag=0);");
        QString sql = QString::fromStdString(
            "Select b.uuid as id,b.faceUrl as img,a.idCard as idcard from '" + str_tableUuid + "' as a, '" +
            str_tableUuid + "_fea' As b  where a.uuid = b.uuid and ( a.del_flag=0 AND b.del_flag=0);");
            "Select b.uuid as id,b.faceUrl as img,a.idCard as idcard from '" + str_tableUuid +
            "' as a, '" + str_tableUuid + "_fea' As b  where a.uuid = b.uuid and ( a.del_flag=0 AND b.del_flag=0);");
        QSqlQuery query(g_syncDbFile);
        query.prepare(sql);
        if (!query.exec()) {
@@ -1530,6 +1670,8 @@
                t_feature_info.id = query.value(0).toString().toStdString();
                t_feature_info.img = query.value(1).toString().toStdString();
                t_feature_info.idcard = query.value(2).toString().toStdString();
//                t_feature_info.enable = query.value(3).toString().toStdString();
//                t_feature_info.monLevel = query.value(4).toString().toStdString();
                dataCache.insert(std::make_pair(t_feature_info.id, t_feature_info));
            }
syncDBTool/ErlangDbTool.h
@@ -21,6 +21,7 @@
#include <stdarg.h>
#include <jsoncpp/json/json.h>
#include <arpa/inet.h>
#include <SqliteToolkit.hpp>
#include "erl_interface.h"
#include "ei.h"
@@ -135,6 +136,8 @@
    private:
        void initCNode();
        bool getExecSqlResult(const std::string &strSql);
    public:
        //#todo setCNodeName
@@ -189,10 +192,27 @@
         * @param TableName
         * @param SyncType true 1||false 0
         * @param BwType   "Black"1||"White"0
         * @param StartTime
         * @param EndTime
         * @return 创建状态
         */
        bool createDatabase(std::string TableType, std::string TableName, bool SyncType, std::string BwType,
                            std::string StartTime = "", std::string EndTime = "");
        /***
         * 创建底库表
         * @param TableType TableType car||person
         * @param TableName
         * @param SyncType  true 1||false 0
         * @param BwType    "Black"1||"White"0
         * @param UploadFlag 是否上传
         * @param CmpThreshold 对比阈值
         * @param Enabled 是否启用
         * @param StartTime
         * @param EndTime
         * @return
         */
        bool createDatabase(std::string t_tableName, FieldValues &fieldValues);
        /***
         * 更新底库表
@@ -205,6 +225,8 @@
        bool updateDatabase(std::string UUID, std::string TableType, std::string TableName, bool SyncType,
                            std::string BwType, std::string StartTime = "", std::string EndTime = "");
        bool updateDatabase(std::string t_tableName, FieldValues &fieldValues);
        /***
         * 删除数据表
         * @param TableType car||person
@@ -213,6 +235,8 @@
         * @return
         */
        bool deleteDatabase(std::string TableType, std::string TableName, bool SyncType);
        bool deleteDatabase(std::string t_tableName);
        /***
         * 查询所有数据表
@@ -242,6 +266,11 @@
                       std::string IdCard = " ", std::string PersonName = " ", std::string Age = " ",
                       std::string Sex = " ", std::string PhoneNum = " ");
        bool
        ErlangTool::ErlangDbTool::addPerson(std::string t_tableName, AddFaceData &faceData, FieldValues &fieldValues);
        bool updatePerson(std::string t_tableName, AddFaceData &faceData, FieldValues &fieldValues);
        vec_AddDataCache addPersons(std::string TableUuid, std::vector<SyncDB::AddPersonInfo> &tmpPer);
        /***
syncDBTool/SyncDB.hpp
@@ -21,6 +21,8 @@
        update_time,
        img,
        idcard,
        enable,
        monLevel,
        evEnd
    };
@@ -36,6 +38,8 @@
        map_Fea_InfoString2Values["update_time"] = Feature_InfoStringValue::update_time;
        map_Fea_InfoString2Values["img"] = Feature_InfoStringValue::img;
        map_Fea_InfoString2Values["idcard"] = Feature_InfoStringValue::idcard;
        map_Fea_InfoString2Values["enable"] = Feature_InfoStringValue::enable;
        map_Fea_InfoString2Values["monitorLevel"] = Feature_InfoStringValue::monLevel;
        map_Fea_InfoString2Values["end"] = evEnd;
    }
@@ -81,6 +85,12 @@
                    case Feature_InfoStringValue::idcard:
                        idcard = value;
                        break;
                    case Feature_InfoStringValue::enable:
                        enable = value;
                        break;
                    case Feature_InfoStringValue::monLevel:
                        monLevel = value;
                        break;
                    default:
                        ERR(key << " is an invalid string. s_mapStringValues now contains "
                                << map_Fea_InfoString2Values.size() << " entries.");
@@ -102,6 +112,9 @@
        std::string update_time;
        std::string img;
        std::string idcard;
        std::string enable;
        std::string monLevel;
//        value is a atom: atomSize:19, atomValue:test@192.168.50.216
//        value is a list:2018-08-08 20:17:11
@@ -271,6 +284,9 @@
        tab_uuid,
        tab_startTime,
        tab_endTime,
        tab_uploadFlag,
        tab_cmpThreshold,
        tab_enabled,
        tab_evEnd
    };
@@ -290,6 +306,9 @@
        map_Tab_InfoString2Values["uuid"] = Table_InfoStringValue::tab_uuid;
        map_Tab_InfoString2Values["startTime"] = Table_InfoStringValue::tab_startTime;
        map_Tab_InfoString2Values["endTime"] = Table_InfoStringValue::tab_endTime;
        map_Tab_InfoString2Values["uploadFlag"] = Table_InfoStringValue::tab_uploadFlag;
        map_Tab_InfoString2Values["cmpThreshold"] = Table_InfoStringValue::tab_cmpThreshold;
        map_Tab_InfoString2Values["enabled"] = Table_InfoStringValue::tab_enabled;
        map_Tab_InfoString2Values["end"] = Table_InfoStringValue::tab_evEnd;
    }
@@ -299,8 +318,8 @@
    struct Table_Info {
    public:
        Table_Info() :
            create_by(""), create_time(""), del_flag(""), tableDesc(""), tableName(""), tableType(""),
            update_time(""), uuid(""), bwType(""), startTime(""), endTime("") {
            create_by(""), create_time(""), del_flag(""), tableDesc(""), tableName(""), tableType(""), update_time(""),
            uuid(""), bwType(""), startTime(""), endTime(""), uploadFlag(""), cmpThreshold(""), enabled("") {
//            Initialize();
        }
@@ -351,6 +370,15 @@
                    case Table_InfoStringValue::tab_endTime:
                        endTime = value;
                        break;
                    case Table_InfoStringValue::tab_uploadFlag:
                        uploadFlag = value;
                        break;
                    case Table_InfoStringValue::tab_cmpThreshold:
                        cmpThreshold = value;
                        break;
                    case Table_InfoStringValue::tab_enabled:
                        enabled = value;
                        break;
                    default:
                        ERR(key << " is an invalid string. s_mapStringValues now contains "
                                << map_Fea_InfoString2Values.size() << " entries.");
@@ -376,6 +404,9 @@
        std::string bwType;
        std::string startTime;
        std::string endTime;
        std::string uploadFlag;
        std::string cmpThreshold;
        std::string enabled;
    private:
    };