//
|
// Created by ps on 19-1-10.
|
//
|
|
#include <opencv2/imgproc.hpp>
|
#include <qt5/QtCore/QDateTime>
|
#include <basic/util/app/AppPreference.hpp>
|
#include "VideoCaptureElementWithRtp.h"
|
#include <VideoToImageMulth/RtspAnalysManager.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, RtspAnalysManager *manager)
|
: m_chanPubID(chanPubID), m_fps(fps), m_running(false),
|
m_waitSignal(false), m_streamTransType(streamTransType),
|
m_gpuIdx(gpuIdx), m_userdata((long) this), m_pManager(manager) {
|
// 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) {
|
|
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(p_this->m_chanPubID, imageName, copyMat);
|
}
|
p_this->submit();
|
}
|
INFO("waitSignalAndEmit is exit...");
|
}, this);
|
waitSignalAndEmit.detach();
|
|
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) {
|
// if(p_this->m_fFmpegDecoderJPG.getRunning()) {
|
usleep(300000);
|
// }else{
|
// p_this->m_running = false;
|
// break;
|
// }
|
}
|
DBG("videoCaptureElementThd stop ...");
|
C_RealVideoStop(lrealhandle);
|
p_this->m_waitSignal = false;
|
DBG("videoCaptureElementThd stop ok...");
|
} else {
|
p_this->m_waitSignal = false;
|
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() {
|
if ((!m_running) || (!m_waitSignal)) {
|
if (reopenTime < 0) {
|
stop();
|
INFO("grabFrame faild, element stopping");
|
return;
|
} else {
|
usleep(reopenTime * 1000);
|
INFO("grabFrame faild, try reopen video: ");
|
startRtpStream(m_streamTransType);
|
return;
|
}
|
}
|
fireConnectors();
|
}
|
|
void BASICGB28181::VideoCaptureElementWithRtp::threadInitial() {
|
|
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;
|
}
|