Blame view

src/decoder/gb28181/rtp/RTPUdpReceiver.cpp 9.44 KB
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
1
2
3
4
5
6
7
8
9
  
  #include "RTPUdpReceiver.h"
  #include <iostream>
  #include <time.h>
  
  #include <thread>
  #include <chrono>
  
  #include "../common_header.h"
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
10
  #include "../sip/SipServer.h"
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  
  
  using namespace std;
  
  #define BUFFERSIZE_1024     4096
  #define BUFFERSIZE_GAP      4096//5120 //1024*5
  
  namespace 
  {
  	const int kVideoFrameSize         = BUFFERSIZE_1024*BUFFERSIZE_1024*5*2;
  	const int kRtpRecvBufferSize      = BUFFERSIZE_1024*BUFFERSIZE_1024*2;
  	const uint16_t kInvalidPort       = 0;
  }; // namespace
  
  class UdpRTPSession : public RTPSession
  {
  public:
  	UdpRTPSession() {}
  	virtual ~UdpRTPSession() {}
  
  private:
  	virtual void OnRTPPacket(RTPPacket* pack, const RTPTime& receiverTime, const RTPAddress* senderAddress)
  	{
  		AddDestination(*senderAddress);
  	}
  
  	virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack, const RTPTime &receivetime,const RTPAddress *senderaddress)
  	{
  		//AddDestination(*senderaddress);
  		//const char* name = "hi~";
  		//SendRTCPAPPPacket(0, (const uint8_t*)name, "keeplive", 8);
  
  		//printf("send rtcp app");
  	}
  };
  
  static int rtp_revc_thread_(void* param)
  {
  	if (!param)
  	{
  		return -1;
  	}
  
  	RTPUdpReceiver* self = (RTPUdpReceiver*)param;
  	return self->OnRtpRecv();
  }
  
  RTPUdpReceiver::RTPUdpReceiver() 
  : m_bRtpExit(false)
  , m_bOpened(false)
  , m_idleCount(-1)
  ,m_noDataCount(-1)
  {
  	m_sessparamsPtr = new RTPSessionParams();
  	m_transparamsPtr = new RTPUDPv4TransmissionParams();
  	m_rtpSessionPtr = new UdpRTPSession();
  }
  
  RTPUdpReceiver::~RTPUdpReceiver()
  {
  	if (IsOpened())
  		Close();
  
  	if(nullptr != m_sessparamsPtr){
  		delete m_sessparamsPtr;
  		m_sessparamsPtr = nullptr;
  	}
  
  	if(nullptr != m_transparamsPtr){
  		delete m_transparamsPtr;
  		m_transparamsPtr = nullptr;
  	}
  
  	if(nullptr != m_rtpSessionPtr){
  		delete m_rtpSessionPtr;
  		m_rtpSessionPtr = nullptr;
  	}
  }
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
90
  bool RTPUdpReceiver::Open(string channel_id)
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
91
  {
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
92
93
94
95
96
97
98
99
  	m_SipChannelId = channel_id;
  
  	int rtpPort = allocRtpPort();
  	if (rtpPort < 0) {
  		return false;
  	}
  	m_rtp_port = rtpPort;
  
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
100
101
102
103
104
  	m_sessparamsPtr->SetUsePollThread(true);
  	m_sessparamsPtr->SetMinimumRTCPTransmissionInterval(10);
  	m_sessparamsPtr->SetOwnTimestampUnit(1.0/90000.0);
  	m_sessparamsPtr->SetAcceptOwnPackets(true);
  	
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
105
  	m_transparamsPtr->SetPortbase(m_rtp_port);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
106
107
  	m_transparamsPtr->SetRTPReceiveBuffer(kRtpRecvBufferSize);
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
108
      LOG_INFO("[{}] port: {}", m_SipChannelId, m_rtp_port);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
109
110
  	
  	int err = m_rtpSessionPtr->Create(*m_sessparamsPtr, m_transparamsPtr);
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
111
112
  	if (err != 0) {	
  		LOG_ERROR("[{}] Create error: {}", m_SipChannelId, err);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
113
114
115
116
  		return false;
  	}
  
  	m_rtpThreadPtr = new std::thread(rtp_revc_thread_, this);
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
117
118
  	if (nullptr == m_rtpThreadPtr) {
  		LOG_ERROR("[{}] Create m_rtpThreadPtr error", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
119
120
  		return false;
  	}
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
121
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
122
  	if (InitPS() != 0) {
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
123
124
125
  		return false;
  	}
  
5b86d771   Hu Chunming   实现GB28181 UDP 基于d...
126
127
  	RequestStream();
  
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
128
  	m_bOpened = true;
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
129
      LOG_INFO("[{}] Open ok", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
130
131
132
133
  
  	return true;
  }
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
134
135
136
137
138
139
140
141
142
143
  bool RTPUdpReceiver::RequestStream() {
  	SipServer* pServer = SipServer::getInstance();
  	int ret = -1;
  	if (pServer){
  		ret = pServer->RequestInvite_UDP(m_SipChannelId.c_str(), m_rtp_port);
  	}
  
  	return (ret > 0) ;
  }
  
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  bool RTPUdpReceiver::IsOpened()
  {
  	return m_bOpened;
  }
  
  void RTPUdpReceiver::Close()
  {
      m_bRtpExit = true;
      
      // rtp接收线程退出
      if (nullptr != m_rtpThreadPtr && m_rtpThreadPtr->joinable())
      {
          m_rtpThreadPtr->join();
  		delete m_rtpThreadPtr;
  		m_rtpThreadPtr = nullptr;
      }
      m_rtpSessionPtr->Destroy();
  
  	ClosePsThread();
  
      m_bOpened = false;
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
166
  	LOG_INFO("[{}] closed.", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
167
168
169
170
171
172
173
174
175
  }
  
  // RTP包线程
  int RTPUdpReceiver::OnRtpRecv()
  {
  	if(nullptr == m_rtpSessionPtr){
  		return -1;
  	}
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
176
  	LOG_INFO("[{}] OnRtpRecv started.", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
177
178
179
180
181
182
183
184
185
  	while (!m_bRtpExit)
  	{
  		//try
  		//{
  			m_rtpSessionPtr->Poll();
  			m_rtpSessionPtr->BeginDataAccess();
  			
  			if (m_rtpSessionPtr->GotoFirstSourceWithData())
  			{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
186
  				// LOG_INFO("OnRtpRecv GotoFirstSourceWithData --{}", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
187
188
189
190
191
192
193
194
      			last_recv_ts = UtilTools::get_cur_time_ms();
  				m_idleCount = 0;
  				m_noDataCount = 0;
  				do
  				{
  					RTPPacket* packet;
  					while ((packet = m_rtpSessionPtr->GetNextPacket()) != NULL) 
  					{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
195
  						// LOG_INFO("OnRtpRecv GetNextPacket --{}", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  						int ret = ParsePacket(packet);
  						m_rtpSessionPtr->DeletePacket(packet);
  						
  						if(ret != 0){
  							m_bRtpExit = true;
  						}
  					}
  				} while (m_rtpSessionPtr->GotoNextSourceWithData());
  			}
  			//else {
  			//	if (m_idleCount != -1)
  			//	{
  			//		++m_idleCount;//流中断计数
  			//	}
  			//	if (m_noDataCount != 0)
  			//	{
  			//		--m_noDataCount;//没流计数
  			//	}
  			//	//if (m_idleCount > 3000) {
  			//	//	     	m_hVodEndFunc(m_usrParam);
  			//	//	    m_idleCount = 0;
  			//	//历史流结束的时候,也会出现超时,这个是正常的
  			//	if(m_usrParam && ((VideoSession *)GetUsrParam())->video_type() == VideoType::ERECORD)
  			//	{
  			//		if (m_idleCount > 10000)
  			//		{
  			//			//这里要判断下历史流是否结束,如果未结束,就设置为流中断
  			//			//由于record_stream_status这个函数返回值不准确,所以增加一个进度条大于80%
  			//			if(record_stream_status(((VideoSession *)GetUsrParam())->streamHandle()))
  			//			{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
226
     // 						LOG_INFO("************Record stream is finished**{}**m_progress = {}********", m_SipChannelId, ((VideoSession *)GetUsrParam())->progress());
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
227
228
229
230
231
232
233
234
235
236
  			//				m_idleCount = -1;
  			//				m_hVodEndFunc(m_usrParam);
     // 						record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle());
     // 						((VideoSession *)GetUsrParam())->streamHandle().clear();
  			//			}
  			//			else 
  			//			{
  			//				//如果此时进度大于80% 算完成吧
  			//				if(((VideoSession *)GetUsrParam())->progress() > 0.80)
  			//				{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
237
     // 							LOG_INFO("************Record stream is overtime**{}**m_progress = {}********", m_SipChannelId, ((VideoSession *)GetUsrParam())->progress());
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
238
239
240
241
242
243
244
245
246
  
  			//					m_idleCount = 0;
  			//					m_hVodEndFunc(m_usrParam);
     // 							record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle());
     // 							((VideoSession *)GetUsrParam())->streamHandle().clear();
  			//				}
  			//				else
  			//				{
  			//					m_idleCount = -1;
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
247
     // 							//LOG_ERROR("************post ERROR_REALSTREAM_INTERRUPT to structure****{}********", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
248
249
250
251
252
253
254
255
256
257
  			//					//发送流中断
  			//					//throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Record time video streaming interruption!");
  			//				}
  			//			}
  			//			 
     //                                                                         
  			//		}
  			//		
  			//		if (m_noDataCount < -200000)//任务开始时没收到流
  			//		{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
258
     // 					//LOG_ERROR("************m_hVodEndFunc(m_usrParam)!!!m_hVodEndFunc(m_usrParam)********{}******", m_SipChannelId);	 
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  			//			m_noDataCount = -1;
  
  			//			//throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Record time video streaming interruption2!");
  			//			//m_hVodEndFunc(m_usrParam);
  			//		}
  			//	}
  			//	else//实时任务断流
  			//	//if (m_usrParam && ((VideoSession *)GetUsrParam())->video_type() == VideoType::EREAL)
  			//	{
  			//       
  			//		//每超过3000次,发送一次send_vedio_eof 时长大约1.5s
  			//		//若是30000,时长大约 18s
  			//		if(m_idleCount > 30000)
  			//		{
     // 					uint64_t cts = UtilTools::get_cur_time_ms();
     // 					float duration_not_recv = (cts - last_recv_ts) / 1000.0;
     // 					
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
276
     // 					//LOG_ERROR("************I haven't  got stream from hik gateway exceed {}s,send eof********{}******", duration_not_recv, m_SipChannelId);	 
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
277
278
279
280
281
282
283
  			//			m_idleCount = -1;
  
  			//			//throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption!");
  			//		} 
  			//		
  			//		if (m_noDataCount < -200000)//任务开始时没收到流
  			//		{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
284
     // 					//LOG_ERROR("************m_noDataCount < -200000********{}******", m_SipChannelId);	 
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
285
286
287
288
289
290
291
292
293
294
  			//			m_noDataCount = -1;
  
  			//			//throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption2!");
  			//		}
  			//		
  			//	}
  			//}
  		//}
    //      catch (GeneralException2& e)
  		//{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
295
    //  		//LOG_ERROR("---> video streaming interruption!<---{}, error: {}", m_SipChannelId, e.err_msg());
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
296
297
298
299
300
301
302
303
304
305
306
  
  		//	byte_buffer bb(64);
    //  		bb << VasCmd::VAS_CMD_REALSTREAM_INTERRUPT << e.err_msg();
  
  		//	if (m_usrParam)
  		//	{
    //  			if (((VideoSession *)GetUsrParam())->msgChan()->is_valid()) {
    //                  try {
    //                      ((VideoSession *)GetUsrParam())->msgChan()->send_msg(bb.data_ptr(), bb.data_size());
    //                  }
    //      			catch (GeneralException2& e) {
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
307
    //          			//LOG_ERROR("[{}] send vas cmd VAS_CMD_REALSTREAM_INTERRUPT error: {}, {}", m_SipChannelId, e.err_code(), e.err_str());
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
308
309
310
311
312
313
314
    //      			}    			
    //              }
  
  		//		//通知网关关闭句柄
  		//		if(!((VideoSession *)GetUsrParam())->streamHandle().empty())
  		//		{
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
315
    //  				LOG_INFO("---->Notify hisense gateway release handle = {} !<----{}", ((VideoSession *)GetUsrParam())->streamHandle().c_str(), m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    //  				if (((VideoSession *)GetUsrParam())->video_type() == VideoType::EREAL)
    //      				real_stream_stop(((VideoSession *)GetUsrParam())->streamHandle());
    //        
    //  				if (((VideoSession *)GetUsrParam())->video_type() == VideoType::ERECORD)
    //      				record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle());
    //                                                
  		//			  //清理保活的句柄
  		//			  ((VideoSession *)GetUsrParam())->streamHandle().clear();
  		//		}
  		//	}
    //    
  		//	bb.bset(0);
  		//
  		//}
  		m_rtpSessionPtr->EndDataAccess();
  
  		std::this_thread::sleep_for(std::chrono::milliseconds(10));
  	}
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
335
  	LOG_INFO("[{}] OnRtpRecv exited.", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
336
337
338
  
  	return 0;
  }