Blame view

src/decoder/gb28181/rtp/RTPUdpReceiver.cpp 9.42 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
126
  		return false;
  	}
  
  	m_bOpened = true;
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
127
      LOG_INFO("[{}] Open ok", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
128
129
130
131
  
  	return true;
  }
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
132
133
134
135
136
137
138
139
140
141
  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 有重大进展...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  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大体的代码,未完...
164
  	LOG_INFO("[{}] closed.", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
165
166
167
168
169
170
171
172
173
  }
  
  // RTP包线程
  int RTPUdpReceiver::OnRtpRecv()
  {
  	if(nullptr == m_rtpSessionPtr){
  		return -1;
  	}
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
174
  	LOG_INFO("[{}] OnRtpRecv started.", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
175
176
177
178
179
180
181
182
183
  	while (!m_bRtpExit)
  	{
  		//try
  		//{
  			m_rtpSessionPtr->Poll();
  			m_rtpSessionPtr->BeginDataAccess();
  			
  			if (m_rtpSessionPtr->GotoFirstSourceWithData())
  			{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
184
  				// LOG_INFO("OnRtpRecv GotoFirstSourceWithData --{}", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
185
186
187
188
189
190
191
192
      			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大体的代码,未完...
193
  						// LOG_INFO("OnRtpRecv GetNextPacket --{}", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
194
195
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
  						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大体的代码,未完...
224
     // 						LOG_INFO("************Record stream is finished**{}**m_progress = {}********", m_SipChannelId, ((VideoSession *)GetUsrParam())->progress());
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
225
226
227
228
229
230
231
232
233
234
  			//				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大体的代码,未完...
235
     // 							LOG_INFO("************Record stream is overtime**{}**m_progress = {}********", m_SipChannelId, ((VideoSession *)GetUsrParam())->progress());
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
236
237
238
239
240
241
242
243
244
  
  			//					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大体的代码,未完...
245
     // 							//LOG_ERROR("************post ERROR_REALSTREAM_INTERRUPT to structure****{}********", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
246
247
248
249
250
251
252
253
254
255
  			//					//发送流中断
  			//					//throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Record time video streaming interruption!");
  			//				}
  			//			}
  			//			 
     //                                                                         
  			//		}
  			//		
  			//		if (m_noDataCount < -200000)//任务开始时没收到流
  			//		{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
256
     // 					//LOG_ERROR("************m_hVodEndFunc(m_usrParam)!!!m_hVodEndFunc(m_usrParam)********{}******", m_SipChannelId);	 
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  			//			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大体的代码,未完...
274
     // 					//LOG_ERROR("************I haven't  got stream from hik gateway exceed {}s,send eof********{}******", duration_not_recv, m_SipChannelId);	 
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
275
276
277
278
279
280
281
  			//			m_idleCount = -1;
  
  			//			//throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption!");
  			//		} 
  			//		
  			//		if (m_noDataCount < -200000)//任务开始时没收到流
  			//		{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
282
     // 					//LOG_ERROR("************m_noDataCount < -200000********{}******", m_SipChannelId);	 
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
283
284
285
286
287
288
289
290
291
292
  			//			m_noDataCount = -1;
  
  			//			//throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption2!");
  			//		}
  			//		
  			//	}
  			//}
  		//}
    //      catch (GeneralException2& e)
  		//{
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
293
    //  		//LOG_ERROR("---> video streaming interruption!<---{}, error: {}", m_SipChannelId, e.err_msg());
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
294
295
296
297
298
299
300
301
302
303
304
  
  		//	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大体的代码,未完...
305
    //          			//LOG_ERROR("[{}] send vas cmd VAS_CMD_REALSTREAM_INTERRUPT error: {}, {}", m_SipChannelId, e.err_code(), e.err_str());
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
306
307
308
309
310
311
312
    //      			}    			
    //              }
  
  		//		//通知网关关闭句柄
  		//		if(!((VideoSession *)GetUsrParam())->streamHandle().empty())
  		//		{
  
74d1e6a8   Hu Chunming   完成gb28181大体的代码,未完...
313
    //  				LOG_INFO("---->Notify hisense gateway release handle = {} !<----{}", ((VideoSession *)GetUsrParam())->streamHandle().c_str(), m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
    //  				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大体的代码,未完...
333
  	LOG_INFO("[{}] OnRtpRecv exited.", m_SipChannelId);
c8285c8d   Hu Chunming   GB28181 UDP 有重大进展...
334
335
336
  
  	return 0;
  }