From 3d4c378b6f65f03f9fab19bdee5decb2be989b92 Mon Sep 17 00:00:00 2001
From: pansen <pansen626@sina.com>
Date: 星期日, 03 三月 2019 16:12:40 +0800
Subject: [PATCH] 添加GB28181解码模块
---
QiaoJiaSystem/GB28181DecoderModel/CMakeLists.txt | 101 +++
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.h | 248 +++++++++
QiaoJiaSystem/GB28181DecoderModel/GB28181Server.cpp | 56 ++
QiaoJiaSystem/GB28181DecoderModel/SpinLock.hpp | 30 +
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h | 94 +++
QiaoJiaSystem/GB28181DecoderModel/GlobalSignalWaitLock.hpp | 115 ++++
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp | 210 +++++++
QiaoJiaSystem/GB28181DecoderModel/main.cpp | 123 ++++
QiaoJiaSystem/CMakeLists.txt | 7
QiaoJiaSystem/GB28181DecoderModel/GB28181Server.h | 93 +++
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp | 536 +++++++++++++++++++
11 files changed, 1,613 insertions(+), 0 deletions(-)
diff --git a/QiaoJiaSystem/CMakeLists.txt b/QiaoJiaSystem/CMakeLists.txt
index 5aad5c3..a2e7f1d 100644
--- a/QiaoJiaSystem/CMakeLists.txt
+++ b/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)
diff --git a/QiaoJiaSystem/GB28181DecoderModel/CMakeLists.txt b/QiaoJiaSystem/GB28181DecoderModel/CMakeLists.txt
new file mode 100644
index 0000000..5d5dd38
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/CMakeLists.txt
@@ -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}
+ )
diff --git a/QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp b/QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp
new file mode 100644
index 0000000..ebf1de9
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp
@@ -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) {
+ //涓嶇瓑寰呭~鍏咃紝鐩存帴杩涜瑙g爜
+ 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 {
+ //缂撳啿鍖轰腑宸茬粡鏈夊お澶氱殑甯т簡,骞朵笖鍓╀綑鐨勫湪缂撳啿闃熷垪鐨刴_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;
+ }
+}
\ No newline at end of file
diff --git a/QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.h b/QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.h
new file mode 100644
index 0000000..1f495fc
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.h
@@ -0,0 +1,248 @@
+//
+// Created by ps on 19-1-11.
+//
+
+//
+// #TODO
+// 鍙互鎶奻fmpeg鐨勬搷浣滄娊鎴愪竴涓璞�
+//
+
+#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甯ф垨鑰匬甯�
+ * #TODO濡傛灉绗竴甯т笉鏄疘甯т細涓嶄細鏈夊紓甯革紵
+ * @param data 甯ф暟鎹湴鍧�
+ * @param datalen 鏁版嵁闀垮害
+ * @param camIdx 鎽勫儚鏈篿d
+ * @return
+ */
+ bool pushInfo(unsigned char *data, int datalen, const std::string &camIdx);
+
+ /***
+ * 寮�鍚В甯х嚎绋�
+ * @param camIdx 鎽勫儚鏈篿d
+ * @param gpuIdx gpuId
+ * @return
+ */
+ bool startThd(const std::string &camIdx, const int &fps, const int &gpuIdx = -1);
+
+ /***
+ * 鍋滄瑙e抚绾跨▼
+ * @return
+ */
+ bool stopThd();
+
+ //****************************
+ std::string GetImageName();
+
+ //淇濆瓨imageName鎵�鍦ㄧ殑瑙嗛鍒皊trPath鐨勮矾寰勪笅
+ 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);
+
+ //涓嶅綍鍍忕殑鏃跺��,濡傛灉淇濆瓨浜嗚冻澶熷鐨勫抚,璋冪敤姝ゅ嚱鏁版竻闄ゆ渶鍓嶉潰鐨勪袱涓狪甯т箣闂寸殑鏁版嵁
+ bool CleanOneKeyFrameOneRange();
+
+ private:
+ //璁板綍鏈�鍚庝竴涓狪甯х殑浣嶇疆
+ int64_t m_last_I_FrameId = -1;
+ //淇濆瓨瑙嗛鐨勮矾寰�
+ std::string m_videoPath;
+ //褰曞儚鐨勪袱绉嶇姸鎬侊紝
+ RecordState_e_t m_recordState = STOP_RECORD;
+
+ //寮�濮嬪綍鍍忕殑甯D
+ int64_t m_startFrameId = 0;
+
+ //鏈�鍚庝竴涓渶瑕佸綍鍍忕殑甯D
+ 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);
+
+ //鍏抽棴鐢╯tartWrite鎵撳紑鐨勬枃浠�
+ int stopWrite();
+
+ //瀵筽acket鍋氳浆鎹�
+ 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);
+
+ /***
+ * 瑁告祦瑙g爜鍑芥暟
+ * @param p_this 绫绘寚閽�
+ */
+ static void BareFlowDecoderThd(FFmpegDecoderJPG *p_this);
+
+ };
+}
+
+
+#endif //GB28181SDK_FFMPEGDECODERJPG_H
diff --git a/QiaoJiaSystem/GB28181DecoderModel/GB28181Server.cpp b/QiaoJiaSystem/GB28181DecoderModel/GB28181Server.cpp
new file mode 100644
index 0000000..88a8c6c
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/GB28181Server.cpp
@@ -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()); // 鍥芥爣鏈嶅姟鐨刬p鍦板潃 (鏈満鐨刬p鍦板潃)
+ //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; // 鏄惁闇�瑕丮D5鍔犲瘑
+ 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;
+}
diff --git a/QiaoJiaSystem/GB28181DecoderModel/GB28181Server.h b/QiaoJiaSystem/GB28181DecoderModel/GB28181Server.h
new file mode 100644
index 0000000..ee5e6fd
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/GB28181Server.h
@@ -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; // 鍥芥爣鏈嶅姟鐨刬p鍦板潃 (鏈満鐨刬p鍦板潃)
+ std::string SvrNatIp; //娉ㄦ剰: 姝ゅ濡傛灉娌℃湁绌跨綉ip鍦板潃涓嶉渶瑕侀厤缃� (涓�鑸儴缃插叕缃戞椂浣跨敤)
+ int SvrPort; // 鍥芥爣鏈嶅姟鐩戝惉鐨勭鍙�
+ std::string SvrPubID; // 鍥芥爣鏈嶅姟鍣ㄧ殑ID
+ bool bMD5Auth; // 鏄惁闇�瑕丮D5鍔犲瘑
+ 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
diff --git a/QiaoJiaSystem/GB28181DecoderModel/GlobalSignalWaitLock.hpp b/QiaoJiaSystem/GB28181DecoderModel/GlobalSignalWaitLock.hpp
new file mode 100644
index 0000000..83b1365
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/GlobalSignalWaitLock.hpp
@@ -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 璁板綍姣忎釜淇″彿鐨剋ait鐘舵�侊紝閬垮厤鏌愪釜淇″彿杩樺湪浣跨敤鍗村皢鍏跺垹闄ょ殑鎯呭喌
+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
diff --git a/QiaoJiaSystem/GB28181DecoderModel/SpinLock.hpp b/QiaoJiaSystem/GB28181DecoderModel/SpinLock.hpp
new file mode 100644
index 0000000..e6e74f8
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/SpinLock.hpp
@@ -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
diff --git a/QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp b/QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp
new file mode 100644
index 0000000..77862e7
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp
@@ -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++;
+ //鍑犲紶閫変竴寮犳斁鍏edis
+ 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;
+}
diff --git a/QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h b/QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h
new file mode 100644
index 0000000..a4fa33b
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h
@@ -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();
+
+ //淇濆瓨瑙嗛鎺ュ彛,浠嶳tspAnalysManager鍙戣捣璋冪敤
+ 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
diff --git a/QiaoJiaSystem/GB28181DecoderModel/main.cpp b/QiaoJiaSystem/GB28181DecoderModel/main.cpp
new file mode 100644
index 0000000..12ed27d
--- /dev/null
+++ b/QiaoJiaSystem/GB28181DecoderModel/main.cpp
@@ -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"; // 鍥芥爣鏈嶅姟鐨刬p鍦板潃 (鏈満鐨刬p鍦板潃)
+ gbServerCfg.SvrPort = 7060; // 鍥芥爣鏈嶅姟鐩戝惉鐨勭鍙�
+ gbServerCfg.SvrPubID = "44120000002000000001"; // 鍥芥爣鏈嶅姟鍣ㄧ殑ID
+ gbServerCfg.bMD5Auth = false; // 鏄惁闇�瑕丮D5鍔犲瘑
+ 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;
+}
\ No newline at end of file
--
Gitblit v1.8.0