QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/GB28181DecoderModel/GB28181Server.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/GB28181DecoderModel/SpinLock.hpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.cpp
@@ -45,7 +45,9 @@ } BASICGB28181::FFmpegDecoderJPG::~FFmpegDecoderJPG() { //清空队列 while (m_rtpQueue.count_queue()) { //#todo delete frameBuffInfo* m_rtpQueue.popNotWait(); } @@ -75,10 +77,9 @@ } #ifdef TestCode DBG(" m_rtpQueue.push before "); DBG(" m_rtpQueue.push befores "); #endif m_rtpQueue. push(info); m_rtpQueue.push(info); #ifdef TestCode DBG(" m_rtpQueue.push after "); #endif @@ -96,10 +97,11 @@ do { // DBG(" m_rtpQueue.pop before "); //从缓存中获取buffinfo 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); @@ -130,7 +132,7 @@ delete[] buffinfo->buff; delete buffinfo; } while (diff > 0); //#todo 触发信号 // DBG("emitSigal(\"read_dataOk\") begin"); // gSignalLock.emitSigal("read_dataOk"); fFmpegDecoderJPG->m_readData = true; @@ -151,12 +153,14 @@ // avformat_network_init(); p_this->ic = avformat_alloc_context(); //创建ffmpeg使用的内存空间 p_this->iobuffer = (unsigned char *) av_malloc(p_this->m_buf_size); if (!p_this->iobuffer) { ERR("av_malloc: err======" << p_this->m_camIdx); p_this->m_running = false; continue; } // 使用回调函数和内存块创建 AVIOContext p_this->avio = avio_alloc_context(p_this->iobuffer, p_this->m_buf_size, 0, p_this, p_this->read_data, NULL, NULL); if (!p_this->avio) { @@ -267,7 +271,7 @@ // BASICGB28181::avframe_to_cvmat(frame).copyTo(p_this->m_image); p_this->m_image = std::move(BASICGB28181::avframe_to_cvmat(p_this->frame)); // 将i帧保存为快照 if (p_this->m_SnapshotNotSaveRet && (p_this->pkt.flags & AV_PKT_FLAG_KEY)) { try { std::string strNewName = "./"; @@ -304,7 +308,7 @@ #ifdef TestCode DBG("emitSigal(\"DecoderImageOK\") begin"); #endif //触发信号 //触发上层信号 gSignalLock.emitSigal(p_this->m_camIdx + "DecoderImageOK"); //#ifdef TestCode // DBG("emitSigal(\"DecoderImageOK\") after"); @@ -349,6 +353,7 @@ } m_camIdx = camIdx; DBG("BareFlowDecoderThd camIdx : " << camIdx); // 启动解码线程 std::thread t_BareFlowDecoder(BareFlowDecoderThd, this); t_BareFlowDecoder.detach(); ); QiaoJiaSystem/GB28181DecoderModel/FFmpegDecoderJPG.h
@@ -48,6 +48,11 @@ static void initFFmpeg(); /*** * AVframe转cvmat * @param frame * @return */ static cv::Mat avframe_to_cvmat(AVFrame *frame); typedef struct _buffInfo { @@ -56,6 +61,7 @@ std::string camIdx; } frameBuffInfo; //************录像模块使用的结构体********************// struct FrameIdPackage_s_t { int64_t m_frameId; AVPacket m_packet; @@ -82,6 +88,7 @@ RECORDING_VIDEO, STOP_RECORD, }; //********************************// // std::map<std::string, MyQueue<frameBuffInfo *> > MapMyQueue; static std::mutex g_mutex; QiaoJiaSystem/GB28181DecoderModel/GB28181Server.cpp
@@ -52,6 +52,7 @@ bool iRet = C_InitSDK(&GBServerParam, &MysqlConnParam, NULL, enventcallback); DBG("iRet is " << iRet); // 等待设备注册 sleep(90); return iRet; QiaoJiaSystem/GB28181DecoderModel/SpinLock.hpp
@@ -6,7 +6,9 @@ #define GB28181SDK_SPINLOCK_H #include <atomic> /*** * 自旋锁,可能会有没锁上的bug */ class SpinLock { public: SpinLock() : m_lock(ATOMIC_FLAG_INIT) {} QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.cpp
@@ -35,17 +35,21 @@ bool BASICGB28181::VideoCaptureElementWithRtp::startRtpStream(int streamTransType) { //等待下层ffmpeg将rtp包解码成为图片后触发信号,然后触发当前类的submit 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) { @@ -54,6 +58,7 @@ p_this->m_picCount.store(0); } // 从ffmpeg解码类中获取图片 p_this->m_fFmpegDecoderJPG.getImage().copyTo(p_this->m_image); { cv::Mat copyMat; @@ -61,6 +66,8 @@ p_this->m_image.copyTo(copyMat); m_pManager->SaveImageToRedis(p_this->m_chanPubID, imageName, copyMat); } /*********/ p_this->submit(); } INFO("waitSignalAndEmit is exit..."); @@ -69,6 +76,7 @@ TryCath( //--------------国标设备或则国标下级平台必须支持GB28181-2016---------------------------------------------- //解码线程,发起点播请求,启动ffmpeg解码模块 std::thread videoCaptureElementThd([&](VideoCaptureElementWithRtp *p_this, int streamType) { DBG("videoCaptureElementThd start..."); StreamTransType_E etype; @@ -93,28 +101,36 @@ } 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; //启动ffmpeg解码模块 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); usleep(300000); // }else{ // p_this->m_running = false; // break; // } } DBG("videoCaptureElementThd stop ..."); //停止点播 C_RealVideoStop(lrealhandle); //将waitSignalAndEmit 线程退出 p_this->m_waitSignal = false; DBG("videoCaptureElementThd stop ok..."); } else { //点播失败 p_this->m_waitSignal = false; p_this->m_running = false; //关闭ffmpeg解码模块 p_this->m_fFmpegDecoderJPG.stopThd(); ERR(p_this->m_chanPubID << " C_RealVideoStart is error lrealhandle is " << lrealhandle); } @@ -157,13 +173,15 @@ // fwrite(data, sizeof(char), datalen, fp11); } #endif //将底层组好的rtp包,存入ffmpeg中的缓存队列 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)) { // 根据reopenTime判断是否需要重启 if (reopenTime < 0) { stop(); INFO("grabFrame faild, element stopping"); QiaoJiaSystem/GB28181DecoderModel/VideoCaptureElementWithRtp.h
@@ -17,6 +17,14 @@ class VideoCaptureElementWithRtp : public basic::PipeElement { public: /*** * VideoCaptureElementWithRtp 视频解码 * @param chanPubID 通道地(摄像机id) * @param fps * @param streamTransType 请求的视频流类型 * @param gpuIdx gpuindex * @param manager 上层类的指针 */ explicit VideoCaptureElementWithRtp(std::string &chanPubID, int fps, int streamTransType, int gpuIdx = -1, RtspAnalysManager *manager = nullptr); @@ -28,6 +36,11 @@ */ bool getRunning(); /*** * 获取图片 * @return */ cv::Mat getImage(); //保存视频接口,从RtspAnalysManager发起调用 @@ -74,7 +87,7 @@ /*** * rtp组包回调函数 * GB28181 SDK rtp组包回调函数 * @param handle * @param datatype * @param frametype