// // Created by ps on 19-1-10. // #include #include #include #include "VideoCaptureElementWithRtp.h" #include //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) { 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(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(p_this->m_chanPubID, 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="<