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"
|
69ee81f3
Hu Chunming
提交websocket clien...
|
10
|
#include "../websocket/WebsocketClient.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
|
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();
}
|
69ee81f3
Hu Chunming
提交websocket clien...
|
58
59
60
61
62
63
64
65
66
67
|
static int connecting_thread_(void* param)
{
if (!param) {
return -1;
}
RTPUdpReceiver* self = (RTPUdpReceiver*)param;
return self->IsConnecting();
}
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
68
|
RTPUdpReceiver::RTPUdpReceiver()
|
69ee81f3
Hu Chunming
提交websocket clien...
|
69
|
:m_bOpened(false)
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
70
71
72
|
, m_idleCount(-1)
,m_noDataCount(-1)
{
|
69ee81f3
Hu Chunming
提交websocket clien...
|
73
|
m_bRtpExit = false;
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
74
75
76
77
78
79
80
|
m_sessparamsPtr = new RTPSessionParams();
m_transparamsPtr = new RTPUDPv4TransmissionParams();
m_rtpSessionPtr = new UdpRTPSession();
}
RTPUdpReceiver::~RTPUdpReceiver()
{
|
69ee81f3
Hu Chunming
提交websocket clien...
|
81
|
m_bRtpExit = true;
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
82
83
84
85
86
87
88
89
90
91
92
|
if(nullptr != m_sessparamsPtr){
delete m_sessparamsPtr;
m_sessparamsPtr = nullptr;
}
if(nullptr != m_transparamsPtr){
delete m_transparamsPtr;
m_transparamsPtr = nullptr;
}
|
69ee81f3
Hu Chunming
提交websocket clien...
|
93
94
95
96
97
98
|
if (nullptr != m_connThreadPtr && m_connThreadPtr->joinable()) {
m_connThreadPtr->join();
delete m_connThreadPtr;
m_connThreadPtr = nullptr;
}
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
99
100
101
102
103
104
|
if(nullptr != m_rtpSessionPtr){
delete m_rtpSessionPtr;
m_rtpSessionPtr = nullptr;
}
}
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
105
|
bool RTPUdpReceiver::Open(string channel_id)
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
106
|
{
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
107
108
|
m_SipChannelId = channel_id;
|
69ee81f3
Hu Chunming
提交websocket clien...
|
109
110
|
m_rtp_port = allocRtpPort();
if (m_rtp_port < 0) {
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
111
112
|
return false;
}
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
113
|
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
114
115
116
117
118
|
m_sessparamsPtr->SetUsePollThread(true);
m_sessparamsPtr->SetMinimumRTCPTransmissionInterval(10);
m_sessparamsPtr->SetOwnTimestampUnit(1.0/90000.0);
m_sessparamsPtr->SetAcceptOwnPackets(true);
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
119
|
m_transparamsPtr->SetPortbase(m_rtp_port);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
120
121
|
m_transparamsPtr->SetRTPReceiveBuffer(kRtpRecvBufferSize);
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
122
|
LOG_INFO("[{}] port: {}", m_SipChannelId, m_rtp_port);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
123
124
|
int err = m_rtpSessionPtr->Create(*m_sessparamsPtr, m_transparamsPtr);
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
125
126
|
if (err != 0) {
LOG_ERROR("[{}] Create error: {}", m_SipChannelId, err);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
127
128
129
130
|
return false;
}
m_rtpThreadPtr = new std::thread(rtp_revc_thread_, this);
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
131
132
|
if (nullptr == m_rtpThreadPtr) {
LOG_ERROR("[{}] Create m_rtpThreadPtr error", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
133
134
|
return false;
}
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
135
|
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
136
|
if (InitPS() != 0) {
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
137
138
139
|
return false;
}
|
69ee81f3
Hu Chunming
提交websocket clien...
|
140
141
142
143
144
145
146
|
// InitPS()成功就得起该线程,因为ClosePsThread是在这里完成的
m_connThreadPtr = new std::thread(connecting_thread_, this);
if (nullptr == m_connThreadPtr) {
LOG_ERROR("[{}] Create m_connThreadPtr error", m_SipChannelId);
return false;
}
|
c3c38c3c
Hu Chunming
代码优化
|
147
148
149
150
151
152
|
bool bReq = RequestStream();
if (!bReq) {
LOG_INFO("[{}] RequestStream failed !", m_SipChannelId);
Close();
return false;
}
|
69ee81f3
Hu Chunming
提交websocket clien...
|
153
|
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
154
|
m_bOpened = true;
|
69ee81f3
Hu Chunming
提交websocket clien...
|
155
|
m_bNoData = false;
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
156
|
LOG_INFO("[{}] Open ok", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
157
158
159
160
|
return true;
}
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
161
162
163
164
165
166
167
168
|
bool RTPUdpReceiver::IsOpened()
{
return m_bOpened;
}
void RTPUdpReceiver::Close()
{
m_bRtpExit = true;
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
169
170
171
172
173
174
175
176
177
|
}
// 收RTP包线程
int RTPUdpReceiver::OnRtpRecv()
{
if(nullptr == m_rtpSessionPtr){
return -1;
}
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
178
|
LOG_INFO("[{}] OnRtpRecv started.", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
179
180
181
182
183
184
185
186
187
|
while (!m_bRtpExit)
{
//try
//{
m_rtpSessionPtr->Poll();
m_rtpSessionPtr->BeginDataAccess();
if (m_rtpSessionPtr->GotoFirstSourceWithData())
{
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
188
|
// LOG_INFO("OnRtpRecv GotoFirstSourceWithData --{}", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
189
190
191
192
193
194
195
196
|
last_recv_ts = UtilTools::get_cur_time_ms();
m_idleCount = 0;
m_noDataCount = 0;
do
{
RTPPacket* packet;
while ((packet = m_rtpSessionPtr->GetNextPacket()) != NULL)
{
|
69ee81f3
Hu Chunming
提交websocket clien...
|
197
|
m_bNoData = false;
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
198
|
// LOG_INFO("OnRtpRecv GetNextPacket --{}", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
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
226
227
228
|
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大体的代码,未完...
|
229
|
// LOG_INFO("************Record stream is finished**{}**m_progress = {}********", m_SipChannelId, ((VideoSession *)GetUsrParam())->progress());
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
230
231
232
233
234
235
236
237
238
239
|
// 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大体的代码,未完...
|
240
|
// LOG_INFO("************Record stream is overtime**{}**m_progress = {}********", m_SipChannelId, ((VideoSession *)GetUsrParam())->progress());
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
241
242
243
244
245
246
247
248
249
|
// 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大体的代码,未完...
|
250
|
// //LOG_ERROR("************post ERROR_REALSTREAM_INTERRUPT to structure****{}********", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
251
252
253
254
255
256
257
258
259
260
|
// //发送流中断
// //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Record time video streaming interruption!");
// }
// }
//
//
// }
//
// if (m_noDataCount < -200000)//任务开始时没收到流
// {
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
261
|
// //LOG_ERROR("************m_hVodEndFunc(m_usrParam)!!!m_hVodEndFunc(m_usrParam)********{}******", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
// 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大体的代码,未完...
|
279
|
// //LOG_ERROR("************I haven't got stream from hik gateway exceed {}s,send eof********{}******", duration_not_recv, m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
280
281
282
283
284
285
286
|
// m_idleCount = -1;
// //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption!");
// }
//
// if (m_noDataCount < -200000)//任务开始时没收到流
// {
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
287
|
// //LOG_ERROR("************m_noDataCount < -200000********{}******", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
288
289
290
291
292
293
294
295
296
297
|
// m_noDataCount = -1;
// //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption2!");
// }
//
// }
//}
//}
// catch (GeneralException2& e)
//{
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
298
|
// //LOG_ERROR("---> video streaming interruption!<---{}, error: {}", m_SipChannelId, e.err_msg());
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
299
300
301
302
303
304
305
306
307
308
309
|
// 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大体的代码,未完...
|
310
|
// //LOG_ERROR("[{}] send vas cmd VAS_CMD_REALSTREAM_INTERRUPT error: {}, {}", m_SipChannelId, e.err_code(), e.err_str());
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
311
312
313
314
315
316
317
|
// }
// }
// //通知网关关闭句柄
// if(!((VideoSession *)GetUsrParam())->streamHandle().empty())
// {
|
74d1e6a8
Hu Chunming
完成gb28181大体的代码,未完...
|
318
|
// LOG_INFO("---->Notify hisense gateway release handle = {} !<----{}", ((VideoSession *)GetUsrParam())->streamHandle().c_str(), m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
|
// 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大体的代码,未完...
|
338
|
LOG_INFO("[{}] OnRtpRecv exited.", m_SipChannelId);
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
339
340
341
342
|
return 0;
}
|
69ee81f3
Hu Chunming
提交websocket clien...
|
343
344
345
346
347
348
349
|
bool RTPUdpReceiver::RequestStream() {
WebsocketClient* pClient = WebsocketClient::getInstance();
if (pClient){
if (pClient->InviteUdp(m_SipChannelId, m_rtp_port, this) < 0) {
return false;
}
}
|
c8285c8d
Hu Chunming
GB28181 UDP 有重大进展...
|
350
|
|
69ee81f3
Hu Chunming
提交websocket clien...
|
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
|
return true;
}
int RTPUdpReceiver::IsConnecting() {
LOG_INFO("[{}] IsConnecting started.", m_SipChannelId);
int count = 0;
while (!m_bRtpExit)
{
if (m_bNoData) {
bool bReq = RequestStream();
if (!bReq) {
LOG_INFO("[{}] RequestStream failed !", m_SipChannelId);
}
wait_times(30); // 等待3s
count++;
if (count > 10) {
// 30s 依然没数据过来,则关闭
m_bRtpExit = true;
break;
}
} else {
m_bNoData = true;
wait_times(100); // 等待10s, 10s之内正常有数据的情况 m_bNoData 已经被置为false
}
}
LOG_DEBUG("[{}] while", m_SipChannelId);
// 结束整个任务
WebsocketClient* pClient = WebsocketClient::getInstance();
if (pClient){
pClient->ByeInvite(m_SipChannelId, m_rtp_port);
}
LOG_DEBUG("[{}] ByeInvite", m_SipChannelId);
// rtp接收线程退出
if (nullptr != m_rtpThreadPtr && m_rtpThreadPtr->joinable())
{
m_rtpThreadPtr->join();
delete m_rtpThreadPtr;
m_rtpThreadPtr = nullptr;
}
LOG_DEBUG("[{}] m_rtpThreadPtr", m_SipChannelId);
m_rtpSessionPtr->Destroy();
LOG_DEBUG("[{}] m_rtpSessionPtr", m_SipChannelId);
ClosePsThread();
m_bOpened = false;
LOG_INFO("[{}] IsConnecting exited.", m_SipChannelId);
return 0;
}
// 对退出命令敏感的延时
bool RTPUdpReceiver::wait_times(int times) {
int count_sleep = times;
while (!m_bRtpExit) {
count_sleep-- ;
if (count_sleep <= 0) {
count_sleep = times;
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
|