Commit 372e629ffafe987b4fd090032566f5086dd43684
1 parent
2d236ac4
gb28181支持TCP数据流
Showing
19 changed files
with
1856 additions
and
657 deletions
.vscode/launch.json
... | ... | @@ -37,6 +37,24 @@ |
37 | 37 | "ignoreFailures": true |
38 | 38 | } |
39 | 39 | ] |
40 | + },{ | |
41 | + "name": "jrtp", | |
42 | + "type": "cppdbg", | |
43 | + "request": "launch", | |
44 | + "program": "${workspaceFolder}/bin/lib/jrtp_exe", | |
45 | + "args": ["40030","t"], | |
46 | + "stopAtEntry": false, | |
47 | + "cwd": "${workspaceFolder}/bin/lib", | |
48 | + "environment": [], | |
49 | + "externalConsole": false, | |
50 | + "MIMode": "gdb", | |
51 | + "setupCommands": [ | |
52 | + { | |
53 | + "description": "Enable pretty-printing for gdb", | |
54 | + "text": "-enable-pretty-printing", | |
55 | + "ignoreFailures": true | |
56 | + } | |
57 | + ] | |
40 | 58 | } |
41 | 59 | ] |
42 | 60 | } |
43 | 61 | \ No newline at end of file | ... | ... |
.vscode/settings.json
jrtp/Makefile
0 → 100644
1 | +XX = g++ | |
2 | + | |
3 | + | |
4 | +PROJECT_ROOT= /mnt/data/cmhu/FFNvDecoder | |
5 | + | |
6 | +DEPEND_DIR = $(PROJECT_ROOT)/bin | |
7 | +SRC_ROOT = $(PROJECT_ROOT)/jrtp | |
8 | +THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty | |
9 | + | |
10 | + | |
11 | +TARGET= $(DEPEND_DIR)/lib/jrtp_exe | |
12 | + | |
13 | + | |
14 | +JRTP_ROOT = $(THIRDPARTY_ROOT)/jrtp_export | |
15 | + | |
16 | + | |
17 | +INCLUDE= -I $(SRC_ROOT)\ | |
18 | + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \ | |
19 | + -I $(JRTP_ROOT)/jthread/include/jthread | |
20 | + | |
21 | +LIBSPATH= -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \ | |
22 | + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a | |
23 | + | |
24 | + | |
25 | +CFLAGS= -g -O0 -fPIC $(INCLUDE) -pthread -lrt -lz -std=c++11 -fvisibility=hidden -Wl,-Bsymbolic -ldl | |
26 | + # -DUNICODE -D_UNICODE | |
27 | + | |
28 | + | |
29 | +SRCS:=$(wildcard $(SRC_ROOT)/*.cpp) | |
30 | +OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS))) | |
31 | + | |
32 | + | |
33 | +$(TARGET):$(OBJS) $(CU_OBJS) | |
34 | + rm -f $(TARGET) | |
35 | + $(XX) -o $@ $^ $(CFLAGS) $(LIBSPATH) $(LIBS) -Wwrite-strings | |
36 | + rm -f *.o | |
37 | + | |
38 | +%.o:$(SRC_ROOT)/%.cpp | |
39 | + $(XX) $(CFLAGS) -c $< | |
40 | + | |
41 | +clean: | |
42 | + rm -f *.o $(TARGET) | |
0 | 43 | \ No newline at end of file | ... | ... |
jrtp/example3.cpp
0 → 100644
1 | +/* | |
2 | + This IPv4 example listens for incoming packets and automatically adds destinations | |
3 | + for new sources. | |
4 | +*/ | |
5 | + | |
6 | +#include "rtpsession.h" | |
7 | +#include "rtppacket.h" | |
8 | +#include "rtpudpv4transmitter.h" | |
9 | +#include "rtptcptransmitter.h" | |
10 | +#include "rtpipv4address.h" | |
11 | +#include "rtptcpaddress.h" | |
12 | +#include "rtpsessionparams.h" | |
13 | +#include "rtperrors.h" | |
14 | +#include "rtpsourcedata.h" | |
15 | +#include <stdlib.h> | |
16 | +#include <stdio.h> | |
17 | +#include <iostream> | |
18 | +#include <string> | |
19 | + | |
20 | +using namespace jrtplib; | |
21 | +using namespace std; | |
22 | + | |
23 | +// | |
24 | +// This function checks if there was a RTP error. If so, it displays an error | |
25 | +// message and exists. | |
26 | +// | |
27 | + | |
28 | +void checkerror(int rtperr) | |
29 | +{ | |
30 | + if (rtperr < 0) | |
31 | + { | |
32 | + std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl; | |
33 | + exit(-1); | |
34 | + } | |
35 | +} | |
36 | + | |
37 | +// | |
38 | +// The new class routine | |
39 | +// | |
40 | + | |
41 | +class MyRTPSession : public RTPSession | |
42 | +{ | |
43 | +protected: | |
44 | + void OnNewSource(RTPSourceData *dat) | |
45 | + { | |
46 | + if (dat->IsOwnSSRC()) | |
47 | + return; | |
48 | + | |
49 | + uint32_t ip; | |
50 | + uint16_t port; | |
51 | + | |
52 | + if (dat->GetRTPDataAddress() != 0) | |
53 | + { | |
54 | + const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress()); | |
55 | + ip = addr->GetIP(); | |
56 | + port = addr->GetPort(); | |
57 | + } | |
58 | + else if (dat->GetRTCPDataAddress() != 0) | |
59 | + { | |
60 | + const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress()); | |
61 | + ip = addr->GetIP(); | |
62 | + port = addr->GetPort()-1; | |
63 | + } | |
64 | + else | |
65 | + return; | |
66 | + | |
67 | + RTPIPv4Address dest(ip,port); | |
68 | + AddDestination(dest); | |
69 | + | |
70 | + struct in_addr inaddr; | |
71 | + inaddr.s_addr = htonl(ip); | |
72 | + std::cout << "Adding destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; | |
73 | + } | |
74 | + | |
75 | + void OnBYEPacket(RTPSourceData *dat) | |
76 | + { | |
77 | + if (dat->IsOwnSSRC()) | |
78 | + return; | |
79 | + | |
80 | + uint32_t ip; | |
81 | + uint16_t port; | |
82 | + | |
83 | + if (dat->GetRTPDataAddress() != 0) | |
84 | + { | |
85 | + const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress()); | |
86 | + ip = addr->GetIP(); | |
87 | + port = addr->GetPort(); | |
88 | + } | |
89 | + else if (dat->GetRTCPDataAddress() != 0) | |
90 | + { | |
91 | + const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress()); | |
92 | + ip = addr->GetIP(); | |
93 | + port = addr->GetPort()-1; | |
94 | + } | |
95 | + else | |
96 | + return; | |
97 | + | |
98 | + RTPIPv4Address dest(ip,port); | |
99 | + DeleteDestination(dest); | |
100 | + | |
101 | + struct in_addr inaddr; | |
102 | + inaddr.s_addr = htonl(ip); | |
103 | + std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; | |
104 | + } | |
105 | + | |
106 | + void OnRemoveSource(RTPSourceData *dat) | |
107 | + { | |
108 | + if (dat->IsOwnSSRC()) | |
109 | + return; | |
110 | + if (dat->ReceivedBYE()) | |
111 | + return; | |
112 | + | |
113 | + uint32_t ip; | |
114 | + uint16_t port; | |
115 | + | |
116 | + if (dat->GetRTPDataAddress() != 0) | |
117 | + { | |
118 | + const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress()); | |
119 | + ip = addr->GetIP(); | |
120 | + port = addr->GetPort(); | |
121 | + } | |
122 | + else if (dat->GetRTCPDataAddress() != 0) | |
123 | + { | |
124 | + const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress()); | |
125 | + ip = addr->GetIP(); | |
126 | + port = addr->GetPort()-1; | |
127 | + } | |
128 | + else | |
129 | + return; | |
130 | + | |
131 | + RTPIPv4Address dest(ip,port); | |
132 | + DeleteDestination(dest); | |
133 | + | |
134 | + struct in_addr inaddr; | |
135 | + inaddr.s_addr = htonl(ip); | |
136 | + std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; | |
137 | + } | |
138 | + | |
139 | + void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled) | |
140 | + { | |
141 | + printf("SSRC %x Got packet (%d bytes) in OnValidatedRTPPacket from source 0x%04x!\n", GetLocalSSRC(), | |
142 | + (int)rtppack->GetPayloadLength(), srcdat->GetSSRC()); | |
143 | + DeletePacket(rtppack); | |
144 | + *ispackethandled = true; | |
145 | + } | |
146 | + | |
147 | + void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t, const void *itemdata, size_t itemlength) | |
148 | + { | |
149 | + char msg[1024]; | |
150 | + | |
151 | + memset(msg, 0, sizeof(msg)); | |
152 | + if (itemlength >= sizeof(msg)) | |
153 | + itemlength = sizeof(msg)-1; | |
154 | + | |
155 | + memcpy(msg, itemdata, itemlength); | |
156 | + printf("SSRC %x Received SDES item (%d): %s from SSRC %x\n", GetLocalSSRC(), (int)t, msg, srcdat->GetSSRC()); | |
157 | + } | |
158 | +}; | |
159 | + | |
160 | +class MyTCPTransmitter : public RTPTCPTransmitter | |
161 | +{ | |
162 | +public: | |
163 | + MyTCPTransmitter() : RTPTCPTransmitter(0){ } | |
164 | + | |
165 | + void OnSendError(SocketType sock) | |
166 | + { | |
167 | + cout << ": Error sending over socket " << sock << ", removing destination" << endl; | |
168 | + DeleteDestination(RTPTCPAddress(sock)); | |
169 | + } | |
170 | + | |
171 | + void OnReceiveError(SocketType sock) | |
172 | + { | |
173 | + cout << ": Error receiving from socket " << sock << ", removing destination" << endl; | |
174 | + DeleteDestination(RTPTCPAddress(sock)); | |
175 | + } | |
176 | +}; | |
177 | + | |
178 | +int udp_mode(int port){ | |
179 | + MyRTPSession sess; | |
180 | + | |
181 | + std::string ipstr; | |
182 | + int status,i,num; | |
183 | + | |
184 | + num = 1000000*30; | |
185 | + | |
186 | + // Now, we'll create a RTP session, set the destination | |
187 | + // and poll for incoming data. | |
188 | + | |
189 | + RTPUDPv4TransmissionParams transparams; | |
190 | + RTPSessionParams sessparams; | |
191 | + | |
192 | + // IMPORTANT: The local timestamp unit MUST be set, otherwise | |
193 | + // RTCP Sender Report info will be calculated wrong | |
194 | + // In this case, we'll be just use 8000 samples per second. | |
195 | + sessparams.SetOwnTimestampUnit(1.0/8000.0); | |
196 | + | |
197 | + sessparams.SetAcceptOwnPackets(true); | |
198 | + transparams.SetPortbase(port); | |
199 | + status = sess.Create(sessparams,&transparams); | |
200 | + checkerror(status); | |
201 | + | |
202 | + std::cout << "begin.." << std::endl; | |
203 | + | |
204 | + for (i = 1 ; i <= num ; i++) | |
205 | + { | |
206 | + sess.BeginDataAccess(); | |
207 | + | |
208 | + // check incoming packets | |
209 | + if (sess.GotoFirstSourceWithData()) | |
210 | + { | |
211 | + do | |
212 | + { | |
213 | + RTPPacket *pack; | |
214 | + | |
215 | + while ((pack = sess.GetNextPacket()) != NULL) | |
216 | + { | |
217 | + // You can examine the data here | |
218 | + printf("Got packet !\n"); | |
219 | + | |
220 | + // we don't longer need the packet, so | |
221 | + // we'll delete it | |
222 | + sess.DeletePacket(pack); | |
223 | + } | |
224 | + } while (sess.GotoNextSourceWithData()); | |
225 | + } | |
226 | + | |
227 | + sess.EndDataAccess(); | |
228 | + | |
229 | +#ifndef RTP_SUPPORT_THREAD | |
230 | + status = sess.Poll(); | |
231 | + checkerror(status); | |
232 | +#endif // RTP_SUPPORT_THREAD | |
233 | + | |
234 | + RTPTime::Wait(RTPTime(0,1)); | |
235 | + } | |
236 | + | |
237 | + sess.BYEDestroy(RTPTime(10,0),0,0); | |
238 | + | |
239 | + return 0; | |
240 | +} | |
241 | + | |
242 | +int tcp_mode(int port){ | |
243 | + int nListener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
244 | + if (nListener < 0) | |
245 | + { | |
246 | + return -1; | |
247 | + } | |
248 | + | |
249 | + sockaddr_in serverAddr; | |
250 | + memset(&serverAddr, 0, sizeof(sockaddr_in)); | |
251 | + serverAddr.sin_family = AF_INET; | |
252 | + serverAddr.sin_port = htons(port); | |
253 | + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |
254 | + int nRet = bind(nListener, (sockaddr*)&serverAddr, sizeof(serverAddr)); | |
255 | + if (nRet == -1) | |
256 | + { | |
257 | + return -1; | |
258 | + } | |
259 | + | |
260 | + if (listen(nListener, 1) == -1) | |
261 | + { | |
262 | + return -1; | |
263 | + } | |
264 | + | |
265 | + sockaddr_in clientAddr; | |
266 | + int nLen = sizeof(sockaddr_in); | |
267 | + int nServer = accept(nListener, (sockaddr*)&clientAddr, (socklen_t * ) &nLen); | |
268 | + if (nServer == -1) | |
269 | + { | |
270 | + return -1; | |
271 | + } | |
272 | + | |
273 | + | |
274 | + int nPackSize = 45678; | |
275 | + RTPSessionParams sessparams; | |
276 | + sessparams.SetProbationType(RTPSources::NoProbation); | |
277 | + sessparams.SetOwnTimestampUnit(90000.0 / 25.0); | |
278 | + sessparams.SetMaximumPacketSize(nPackSize + 64); | |
279 | + | |
280 | + MyTCPTransmitter trans; | |
281 | + int status = trans.Init(true); | |
282 | + status = trans.Create(65535, NULL); | |
283 | + | |
284 | + MyRTPSession sess; | |
285 | + status = sess.Create(sessparams, &trans); | |
286 | + if (status < 0) | |
287 | + { | |
288 | + std::cout << "create session error!!" << std::endl; | |
289 | + return -1; | |
290 | + } | |
291 | + | |
292 | + sess.AddDestination(RTPTCPAddress(nServer)); | |
293 | + | |
294 | + std::cout << "begin.." << std::endl; | |
295 | + | |
296 | + while (true) | |
297 | + { | |
298 | + RTPTime::Wait(RTPTime(1,0)); | |
299 | + } | |
300 | + | |
301 | + | |
302 | + while(true){ | |
303 | + sess.BeginDataAccess(); | |
304 | + | |
305 | + // check incoming packets | |
306 | + if (sess.GotoFirstSourceWithData()) | |
307 | + { | |
308 | + do | |
309 | + { | |
310 | + RTPPacket *pack; | |
311 | + | |
312 | + while ((pack = sess.GetNextPacket()) != NULL) | |
313 | + { | |
314 | + // You can examine the data here | |
315 | + printf("Got packet !\n"); | |
316 | + | |
317 | + // we don't longer need the packet, so | |
318 | + // we'll delete it | |
319 | + sess.DeletePacket(pack); | |
320 | + } | |
321 | + } while (sess.GotoNextSourceWithData()); | |
322 | + } | |
323 | + | |
324 | + sess.EndDataAccess(); | |
325 | + | |
326 | +#ifndef RTP_SUPPORT_THREAD | |
327 | + status = sess.Poll(); | |
328 | + checkerror(status); | |
329 | +#endif // RTP_SUPPORT_THREAD | |
330 | + | |
331 | + RTPTime::Wait(RTPTime(1,0)); | |
332 | + } | |
333 | + | |
334 | + sess.BYEDestroy(RTPTime(10,0),0,0); | |
335 | + | |
336 | + return 0; | |
337 | +} | |
338 | +// | |
339 | +// The main routine | |
340 | +// | |
341 | + | |
342 | +int main(int argc, char* argv[]){ | |
343 | + | |
344 | + int port = atoi(argv[1]); | |
345 | + std::cout << "port:" << port << std::endl; | |
346 | + | |
347 | + while (true) | |
348 | + { | |
349 | + int ch = getchar(); | |
350 | + if (ch == 'q') | |
351 | + { | |
352 | + break; | |
353 | + } | |
354 | + | |
355 | + switch (ch) | |
356 | + { | |
357 | + case 'u': | |
358 | + udp_mode(port); | |
359 | + break; | |
360 | + case 't': | |
361 | + tcp_mode(port); | |
362 | + break; | |
363 | + default: | |
364 | + break; | |
365 | + } | |
366 | + | |
367 | + /* code */ | |
368 | + } | |
369 | + | |
370 | + return 0; | |
371 | +} | |
372 | + | ... | ... |
jrtp/tcp_server.cpp
0 → 100644
1 | +/* | |
2 | + This IPv4 example listens for incoming packets and automatically adds destinations | |
3 | + for new sources. | |
4 | +*/ | |
5 | + | |
6 | +#include "rtpsession.h" | |
7 | +#include "rtppacket.h" | |
8 | +#include "rtpudpv4transmitter.h" | |
9 | +#include "rtptcptransmitter.h" | |
10 | +#include "rtpipv4address.h" | |
11 | +#include "rtptcpaddress.h" | |
12 | +#include "rtpsessionparams.h" | |
13 | +#include "rtperrors.h" | |
14 | +#include "rtpsourcedata.h" | |
15 | +#include <stdlib.h> | |
16 | +#include <stdio.h> | |
17 | +#include <iostream> | |
18 | +#include <string> | |
19 | +#include <thread> | |
20 | +#include <chrono> | |
21 | +#include <unistd.h> | |
22 | + | |
23 | +#include <netinet/tcp.h> | |
24 | +#include <sys/types.h> | |
25 | +#include <sys/socket.h> | |
26 | + | |
27 | +using namespace jrtplib; | |
28 | +using namespace std; | |
29 | + | |
30 | +// | |
31 | +// This function checks if there was a RTP error. If so, it displays an error | |
32 | +// message and exists. | |
33 | +// | |
34 | + | |
35 | +void checkerror(int rtperr) | |
36 | +{ | |
37 | + if (rtperr < 0) | |
38 | + { | |
39 | + std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl; | |
40 | + exit(-1); | |
41 | + } | |
42 | +} | |
43 | + | |
44 | +static long long get_cur_time(){ | |
45 | + chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMs | |
46 | + = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | |
47 | + | |
48 | + return tpMs.time_since_epoch().count(); | |
49 | +} | |
50 | + | |
51 | +// | |
52 | +// The new class routine | |
53 | +// | |
54 | + | |
55 | +// class MyRTPSession : public RTPSession | |
56 | +// { | |
57 | +// protected: | |
58 | + | |
59 | +// void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled) | |
60 | +// { | |
61 | +// // printf("timestamp: %ld SSRC %x Got packet (%d bytes) in OnValidatedRTPPacket from source 0x%04x!\n", get_cur_time(), GetLocalSSRC(), | |
62 | +// // (int)rtppack->GetPayloadLength(), srcdat->GetSSRC()); | |
63 | +// DeletePacket(rtppack); | |
64 | +// *ispackethandled = true; | |
65 | +// } | |
66 | + | |
67 | +// void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t, const void *itemdata, size_t itemlength) | |
68 | +// { | |
69 | +// char msg[1024]; | |
70 | + | |
71 | +// memset(msg, 0, sizeof(msg)); | |
72 | +// if (itemlength >= sizeof(msg)) | |
73 | +// itemlength = sizeof(msg)-1; | |
74 | + | |
75 | +// memcpy(msg, itemdata, itemlength); | |
76 | +// // printf("SSRC %x Received SDES item (%d): %s from SSRC %x\n", GetLocalSSRC(), (int)t, msg, srcdat->GetSSRC()); | |
77 | +// } | |
78 | + | |
79 | +// virtual void OnRTPPacket(RTPPacket* pack, const RTPTime& receiverTime, const RTPAddress* senderAddress) | |
80 | +// { | |
81 | +// AddDestination(*senderAddress); | |
82 | +// } | |
83 | + | |
84 | +// virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack, const RTPTime &receivetime,const RTPAddress *senderaddress) | |
85 | +// { | |
86 | +// //AddDestination(*senderaddress); | |
87 | +// //const char* name = "hi~"; | |
88 | +// //SendRTCPAPPPacket(0, (const uint8_t*)name, "keeplive", 8); | |
89 | + | |
90 | +// printf("send rtcp app"); | |
91 | +// } | |
92 | +// }; | |
93 | + | |
94 | +bool bSocket = false; | |
95 | + | |
96 | +class MyTCPTransmitter : public RTPTCPTransmitter | |
97 | +{ | |
98 | +public: | |
99 | + MyTCPTransmitter() : RTPTCPTransmitter(0){ } | |
100 | + | |
101 | + void OnSendError(SocketType sock) | |
102 | + { | |
103 | + cout << "timestamp: " << get_cur_time() << " : Error sending over socket " << sock << ", removing destination" << endl; | |
104 | + DeleteDestination(RTPTCPAddress(sock)); | |
105 | + | |
106 | + bSocket = false; | |
107 | + } | |
108 | + | |
109 | + void OnReceiveError(SocketType sock) | |
110 | + { | |
111 | + cout << ": Error receiving from socket " << sock << ", removing destination" << endl; | |
112 | + DeleteDestination(RTPTCPAddress(sock)); | |
113 | + } | |
114 | +}; | |
115 | + | |
116 | +RTPSession sess; | |
117 | +MyTCPTransmitter* trans; | |
118 | +RTPSessionParams sessparams; | |
119 | + | |
120 | +int thread_func(void* param){ | |
121 | + | |
122 | + cout << "thread started..." << endl; | |
123 | + | |
124 | + int* p = (int*) param ; | |
125 | + sockaddr_in clientAddr; | |
126 | + int nLen = sizeof(sockaddr_in); | |
127 | + int nServer = -1;//accept(*p, (sockaddr*)&clientAddr, (socklen_t * ) &nLen); | |
128 | + // if (nServer == -1){ | |
129 | + // return -1; | |
130 | + // } | |
131 | + | |
132 | + cout << "timestamp: " << get_cur_time() << " while() start" << endl; | |
133 | + | |
134 | + while(true){ | |
135 | + | |
136 | + while (!bSocket) | |
137 | + { | |
138 | + nServer = accept(*p, (sockaddr*)&clientAddr, (socklen_t * ) &nLen); | |
139 | + if (nServer == -1) | |
140 | + { | |
141 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
142 | + continue; | |
143 | + } | |
144 | + | |
145 | + cout << "nServer = " << nServer << endl; | |
146 | + sess.AddDestination(RTPTCPAddress(nServer)); | |
147 | + bSocket = true; | |
148 | + break; | |
149 | + } | |
150 | + | |
151 | + sess.BeginDataAccess(); | |
152 | + | |
153 | + // check incoming packets | |
154 | + if (sess.GotoFirstSourceWithData()) | |
155 | + { | |
156 | + do | |
157 | + { | |
158 | + RTPPacket *pack; | |
159 | + | |
160 | + while ((pack = sess.GetNextPacket()) != NULL) | |
161 | + { | |
162 | + // You can examine the data here | |
163 | + // printf("Got packet !\n"); | |
164 | + cout << "Got packet ! timestamp: " << get_cur_time() << endl; | |
165 | + | |
166 | + // we don't longer need the packet, so | |
167 | + // we'll delete it | |
168 | + sess.DeletePacket(pack); | |
169 | + } | |
170 | + } while (sess.GotoNextSourceWithData()); | |
171 | + } | |
172 | + | |
173 | + sess.EndDataAccess(); | |
174 | + | |
175 | + sess.Poll(); | |
176 | + | |
177 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
178 | + } | |
179 | + | |
180 | + close(*p); | |
181 | + | |
182 | + // sess.BYEDestroy(RTPTime(10,0),0,0); | |
183 | +} | |
184 | + | |
185 | +int nListener = -1; | |
186 | +int tcp_mode(int port){ | |
187 | + nListener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
188 | + if (nListener < 0) | |
189 | + { | |
190 | + return -1; | |
191 | + } | |
192 | + | |
193 | + sockaddr_in serverAddr; | |
194 | + memset(&serverAddr, 0, sizeof(sockaddr_in)); | |
195 | + serverAddr.sin_family = AF_INET; | |
196 | + serverAddr.sin_port = htons(port); | |
197 | + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |
198 | + int nRet = bind(nListener, (sockaddr*)&serverAddr, sizeof(serverAddr)); | |
199 | + if (nRet == -1) | |
200 | + { | |
201 | + return -1; | |
202 | + } | |
203 | + | |
204 | + if (listen(nListener, 1) == -1) | |
205 | + { | |
206 | + return -1; | |
207 | + } | |
208 | + | |
209 | + int nPackSize = 45678; | |
210 | + | |
211 | + sessparams.SetProbationType(RTPSources::NoProbation); | |
212 | + sessparams.SetOwnTimestampUnit(90000.0 / 25.0); | |
213 | + sessparams.SetMaximumPacketSize(nPackSize + 64); | |
214 | + | |
215 | + trans = new MyTCPTransmitter(); | |
216 | + int status = trans->Init(false); | |
217 | + status = trans->Create(65535, NULL); | |
218 | + | |
219 | + status = sess.Create(sessparams, trans); | |
220 | + if (status < 0) | |
221 | + { | |
222 | + std::cout << "create session error!!" << std::endl; | |
223 | + return -1; | |
224 | + } | |
225 | + | |
226 | + std::cout << "begin.." << std::endl; | |
227 | + | |
228 | + thread* t = new std::thread(thread_func, &nListener); | |
229 | + | |
230 | + return 0; | |
231 | +} | |
232 | +// | |
233 | +// The main routine | |
234 | +// | |
235 | + | |
236 | +int main(int argc, char* argv[]){ | |
237 | + | |
238 | + tcp_mode(40032); | |
239 | + | |
240 | + while(getchar() =='q'); | |
241 | + | |
242 | + return 0; | |
243 | +} | |
244 | + | ... | ... |
src/AbstractDecoder.h
... | ... | @@ -32,6 +32,8 @@ typedef void(*POST_DECODE_CALLBACK)(const void * userPtr, AVFrame * gpuFrame); |
32 | 32 | |
33 | 33 | typedef void(*DECODE_FINISHED_CALLBACK)(const void* userPtr); |
34 | 34 | |
35 | +typedef bool(*DECODE_REQUEST_STREAM_CALLBACK)(); | |
36 | + | |
35 | 37 | struct FFDecConfig{ |
36 | 38 | string uri; // 视频地址 |
37 | 39 | POST_DECODE_CALLBACK post_decoded_cbk; // 解码数据回调接口 |
... | ... | @@ -41,6 +43,7 @@ struct FFDecConfig{ |
41 | 43 | int skip_frame{1}; // 跳帧数 |
42 | 44 | |
43 | 45 | int port; // gb28181接收数据的端口号 |
46 | + DECODE_REQUEST_STREAM_CALLBACK request_stream_cbk; // gb28181请求流 | |
44 | 47 | }; |
45 | 48 | |
46 | 49 | enum DECODER_TYPE{ | ... | ... |
src/FFNvDecoder.cpp
... | ... | @@ -69,6 +69,9 @@ bool FFNvDecoder::init(FFDecConfig& cfg) |
69 | 69 | m_bReal = true; |
70 | 70 | } |
71 | 71 | |
72 | + post_decoded_cbk = cfg.post_decoded_cbk; | |
73 | + decode_finished_cbk = cfg.decode_finished_cbk; | |
74 | + | |
72 | 75 | return init(cfg.uri.c_str(), cfg.gpuid.c_str(),cfg.force_tcp); |
73 | 76 | } |
74 | 77 | ... | ... |
src/FFNvDecoderManager.cpp
... | ... | @@ -15,13 +15,12 @@ AbstractDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){ |
15 | 15 | if (config.cfg.post_decoded_cbk == nullptr || config.cfg.decode_finished_cbk== nullptr){ |
16 | 16 | return nullptr; |
17 | 17 | } |
18 | - | |
19 | 18 | |
20 | 19 | std::lock_guard<std::mutex> l(m_mutex); |
21 | 20 | |
22 | 21 | auto it = decoderMap.find(config.name); |
23 | 22 | if (it != decoderMap.end()){ |
24 | - LOG_ERROR("已存在name所标记的解码器"); | |
23 | + LOG_ERROR("已存在name为{}的解码器", config.name); | |
25 | 24 | return nullptr; |
26 | 25 | } |
27 | 26 | |
... | ... | @@ -41,8 +40,6 @@ AbstractDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){ |
41 | 40 | if (bRet) |
42 | 41 | { |
43 | 42 | dec->setName(config.name) ; |
44 | - dec->post_decoded_cbk = config.cfg.post_decoded_cbk; | |
45 | - dec->decode_finished_cbk = config.cfg.decode_finished_cbk; | |
46 | 43 | decoderMap[config.name] = dec; |
47 | 44 | |
48 | 45 | LOG_INFO("[{}][{}]- 解码器初始化成功",config.name, config.cfg.uri); | ... | ... |
src/Makefile
... | ... | @@ -30,7 +30,7 @@ INCLUDE= -I $(DEPEND_DIR)/include \ |
30 | 30 | |
31 | 31 | LIBSPATH= -L $(DEPEND_DIR)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \ |
32 | 32 | -L $(CUDA_ROOT)/lib64 -lcuda -lcudart -lnvcuvid -lcurand -lcublas -lnvjpeg \ |
33 | - -L $(SPDLOG_ROOT)/lib64 -l:libspdlog.a \ | |
33 | + -L $(SPDLOG_ROOT) -l:libspdlog.a \ | |
34 | 34 | -L $(JRTP_ROOT)/jthread/lib -l:libjthread.a \ |
35 | 35 | -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a |
36 | 36 | ... | ... |
src/gb28181/FFGB28181Decoder.cpp
... | ... | @@ -12,6 +12,9 @@ extern "C" { |
12 | 12 | |
13 | 13 | #include "../logger.hpp" |
14 | 14 | |
15 | +#include"RTPTcpReceiver.h" | |
16 | +#include"RTPUdpReceiver.h" | |
17 | + | |
15 | 18 | #define ECLOSED 0 |
16 | 19 | #define ECLOSING 1 |
17 | 20 | #define ERUNNING 2 |
... | ... | @@ -19,14 +22,14 @@ extern "C" { |
19 | 22 | |
20 | 23 | static void RTP_Stream_CallBack(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts) |
21 | 24 | { |
22 | - FFGB28181Decoder* session = (FFGB28181Decoder*)userdata; | |
23 | - session->stream_callback(videoType, data, len, isKey, pts, localPts); | |
25 | + FFGB28181Decoder* decoder = (FFGB28181Decoder*)userdata; | |
26 | + decoder->stream_callback(videoType, data, len, isKey, pts, localPts); | |
24 | 27 | } |
25 | 28 | |
26 | 29 | static void RTP_Stream_End_CallBack(void* userdata) |
27 | 30 | { |
28 | - FFGB28181Decoder* session = (FFGB28181Decoder*)userdata; | |
29 | - session->stream_end_callback(); | |
31 | + FFGB28181Decoder* decoder = (FFGB28181Decoder*)userdata; | |
32 | + decoder->stream_end_callback(); | |
30 | 33 | } |
31 | 34 | |
32 | 35 | FFGB28181Decoder::FFGB28181Decoder() { |
... | ... | @@ -59,20 +62,30 @@ void FFGB28181Decoder::close(){ |
59 | 62 | |
60 | 63 | m_status = ECLOSING; |
61 | 64 | |
62 | - LOG_INFO("real decode thread exit success 1--{}", m_dec_name); | |
65 | + LOG_DEBUG("real decode thread exit success 1--{}", m_dec_name); | |
66 | + | |
67 | + if(nullptr != m_rtpPtr){ | |
68 | + if (m_rtpPtr->IsOpened()) { | |
69 | + m_rtpPtr->Close(); | |
70 | + LOG_DEBUG("real decode thread exit success 2--{}", m_dec_name); | |
71 | + } | |
63 | 72 | |
64 | - if (m_rtp.IsOpened()) { | |
65 | - m_rtp.Close(); | |
66 | - LOG_INFO("real decode thread exit success 4--{}", m_dec_name); | |
73 | + delete m_rtpPtr; | |
74 | + m_rtpPtr = nullptr; | |
67 | 75 | } |
68 | 76 | |
69 | - stream_end_callback(); | |
77 | + LOG_INFO("解码器关闭成功 --{}", m_dec_name); | |
70 | 78 | |
71 | 79 | m_status = ECLOSED; |
72 | 80 | } |
73 | 81 | |
74 | 82 | bool FFGB28181Decoder::init(FFDecConfig& cfg){ |
75 | - if (m_rtp.IsOpened()){ | |
83 | + if(cfg.force_tcp){ | |
84 | + m_rtpPtr = new RTPTcpReceiver(); | |
85 | + }else{ | |
86 | + m_rtpPtr = new RTPUdpReceiver(); | |
87 | + } | |
88 | + if(nullptr == m_rtpPtr){ | |
76 | 89 | return false; |
77 | 90 | } |
78 | 91 | |
... | ... | @@ -82,12 +95,23 @@ bool FFGB28181Decoder::init(FFDecConfig& cfg){ |
82 | 95 | |
83 | 96 | m_gpuid = atoi(cfg.gpuid.c_str()); |
84 | 97 | |
85 | - m_rtp.SetDeviceID(m_dec_name); | |
98 | + m_rtpPtr->SetDeviceID(m_dec_name); | |
99 | + | |
100 | + if(cfg.request_stream_cbk == nullptr){ | |
101 | + LOG_INFO("request_stream_cbk 为 nullptr -- {}", m_dec_name); | |
102 | + return false; | |
103 | + } | |
104 | + | |
105 | + post_decoded_cbk = cfg.post_decoded_cbk; | |
106 | + decode_finished_cbk = cfg.decode_finished_cbk; | |
107 | + m_rtpPtr->SetRequestStreamCallback(cfg.request_stream_cbk); | |
86 | 108 | |
87 | 109 | m_port = cfg.port; |
88 | 110 | |
89 | 111 | m_cfg = cfg; |
90 | 112 | |
113 | + LOG_INFO("init - {} : ", m_dec_name, m_port); | |
114 | + | |
91 | 115 | return true; |
92 | 116 | } |
93 | 117 | |
... | ... | @@ -95,10 +119,12 @@ bool FFGB28181Decoder::start() { |
95 | 119 | |
96 | 120 | m_status = ERUNNING; |
97 | 121 | |
98 | - m_rtp.SetOutputCallback(RTP_Stream_CallBack, this); | |
99 | - m_rtp.SetVodEndCallback(RTP_Stream_End_CallBack, this); | |
122 | + m_rtpPtr->SetOutputCallback(RTP_Stream_CallBack, this); | |
123 | + m_rtpPtr->SetVodEndCallback(RTP_Stream_End_CallBack, this); | |
100 | 124 | |
101 | - return m_rtp.Open((uint16_t)m_port); | |
125 | + LOG_INFO("start - {} {}: ", m_dec_name, m_port); | |
126 | + | |
127 | + return m_rtpPtr->Open((uint16_t)m_port); | |
102 | 128 | } |
103 | 129 | |
104 | 130 | void FFGB28181Decoder::setDecKeyframe(bool bKeyframe){ |
... | ... | @@ -135,6 +161,7 @@ void FFGB28181Decoder::stream_callback(int videoType, char* data, int len, int i |
135 | 161 | AVDictionary *gpu_options = nullptr; |
136 | 162 | |
137 | 163 | if (m_pAVCodecCtx == nullptr) { |
164 | + LOG_INFO("frame data is zero --{}", m_dec_name); | |
138 | 165 | if (VIDEO_TYPE_H264 == videoType) { |
139 | 166 | if (m_gpuid >= 0){ |
140 | 167 | m_pAVCodec = avcodec_find_decoder_by_name("h264_cuvid"); |
... | ... | @@ -314,5 +341,5 @@ bool FFGB28181Decoder::isSurport(FFDecConfig& cfg){ |
314 | 341 | } |
315 | 342 | |
316 | 343 | int FFGB28181Decoder::getCachedQueueLength(){ |
317 | - return m_rtp.GetPsFrameListSize(); | |
344 | + return m_rtpPtr->GetPsFrameListSize(); | |
318 | 345 | } |
319 | 346 | \ No newline at end of file | ... | ... |
src/gb28181/FFGB28181Decoder.h
src/gb28181/RTPReceiver.cpp
1 | - | |
2 | 1 | #include "RTPReceiver.h" |
3 | -#include <iostream> | |
4 | -#include <time.h> | |
5 | - | |
6 | -#include <thread> | |
7 | -#include <chrono> | |
8 | - | |
2 | +#include "rtppacket.h" | |
9 | 3 | #include "../logger.hpp" |
10 | - | |
11 | -using namespace std; | |
4 | +#include <thread> | |
12 | 5 | |
13 | 6 | #define BUFFERSIZE_1024 1024 |
14 | -#define BUFFERSIZE_GAP 1024//5120 //1024*5 | |
7 | +const int kVideoFrameSize = BUFFERSIZE_1024*BUFFERSIZE_1024*5*2; | |
15 | 8 | |
16 | -namespace | |
9 | +// PS解包器回调 | |
10 | +static int ReceivePESFunction(unsigned char streamid, void * data, int size, uint64_t pts, uint64_t localPts, bool key, void* param) | |
17 | 11 | { |
18 | - const int kH264EndFlag = 0x00000001; | |
19 | - const int kH264EndFlag_ = 0x000001; | |
20 | - const int kMpeg4IEndFlag = 0x000001B0; | |
21 | - const int kMpeg4PEndFlag = 0x000001B6; | |
22 | - const int kSvacEndFlag = 0x000001B6; | |
23 | - const int kVideoFrameSize = BUFFERSIZE_1024*BUFFERSIZE_1024*5*2; | |
24 | - const int kRtpRecvBufferSize = BUFFERSIZE_1024*BUFFERSIZE_1024*2; | |
25 | - const int kSockBufferSize = BUFFERSIZE_1024*BUFFERSIZE_1024*2; | |
26 | - const uint16_t kInvalidPort = 0; | |
27 | - | |
28 | - // PS解包器回调 | |
29 | - int ReceivePESFunction(unsigned char streamid, void * data, int size, uint64_t pts, uint64_t localPts, bool key, void* param) | |
12 | + if (NULL != data && size > 0) | |
13 | + { | |
14 | + ((RTPReceiver*)param)->OnPsDemux(streamid, (BYTE*)data, size, key, (uint64_t)pts, (uint64_t)localPts); | |
15 | + } | |
16 | + return 0; | |
17 | +} | |
18 | + | |
19 | +static int ps_demuxer_thread_(void* param) | |
20 | +{ | |
21 | + if (!param) | |
30 | 22 | { |
31 | - if (NULL != data && size > 0) | |
32 | - { | |
33 | - ((RTPReceiver*)param)->OnPsDemux(streamid, (BYTE*)data, size, key, (uint64_t)pts, (uint64_t)localPts); | |
34 | - } | |
35 | - return 0; | |
23 | + return -1; | |
36 | 24 | } |
37 | 25 | |
38 | -}; // namespace | |
39 | - | |
40 | -static long long get_cur_time() { | |
41 | - // 获取操作系统当前时间点(精确到微秒) | |
42 | - chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | |
43 | - = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | |
44 | - // (微秒精度的)时间点 => (微秒精度的)时间戳 | |
45 | - return tpMicro.time_since_epoch().count(); | |
26 | + RTPReceiver* self = (RTPReceiver*)param; | |
27 | + return self->OnPsProcess(); | |
46 | 28 | } |
47 | 29 | |
48 | -RTPReceiver::RTPReceiver() | |
49 | -: m_localPort(kInvalidPort) | |
50 | -, m_bRtpExit(false) | |
51 | -, m_bPsExit(false) | |
52 | -, m_h264DataFunc(NULL) | |
53 | -, m_usrParam(NULL) | |
54 | -, m_bOpened(false) | |
55 | -, m_hVodEndFunc(NULL) | |
56 | -, m_LastPTS(-1) | |
30 | +RTPReceiver::RTPReceiver() | |
31 | +:m_LastPTS(-1) | |
57 | 32 | , m_LastIsKeyFrame(0) |
58 | 33 | , m_SliceBuf(1024*1024) |
59 | -, m_idleCount(-1) | |
60 | -,m_noDataCount(-1) | |
34 | +, m_h264DataFunc(NULL) | |
35 | +, m_hVodEndFunc(NULL) | |
36 | +, m_usrParam(NULL) | |
37 | +, m_bPsExit(false) | |
38 | +, m_psThreadPtr(nullptr) | |
61 | 39 | { |
62 | - m_LastStreamType=0; | |
40 | + m_LastStreamType = 0; | |
41 | + recvTmpBuf = new BYTE[kVideoFrameSize]; | |
63 | 42 | } |
64 | 43 | |
65 | -RTPReceiver::~RTPReceiver() | |
66 | -{ | |
67 | - if (IsOpened()) | |
68 | - Close(); | |
69 | - | |
70 | - LOG_INFO("RTPReceiver::~RTPReceiver() destruct OK--{}", m_deviceID); | |
44 | +RTPReceiver::~RTPReceiver(){ | |
45 | + if(recvTmpBuf != nullptr){ | |
46 | + delete[] recvTmpBuf; | |
47 | + } | |
71 | 48 | } |
72 | 49 | |
73 | 50 | void RTPReceiver::SetOutputCallback(CallBack_Stream cb, void* param) |
... | ... | @@ -82,376 +59,36 @@ void RTPReceiver::SetVodEndCallback(CallBack_VodFileEnd cb, void* param) |
82 | 59 | m_usrParam = param; |
83 | 60 | } |
84 | 61 | |
85 | -int RTPReceiver::rtp_revc_thread_(void* param) | |
86 | -{ | |
87 | - if (!param) | |
88 | - { | |
89 | - return -1; | |
90 | - } | |
91 | - | |
92 | - RTPReceiver* self = (RTPReceiver*)param; | |
93 | - return self->OnRtpRecv(); | |
62 | +void RTPReceiver::SetRequestStreamCallback(CallBack_Request_Stream cb){ | |
63 | + m_callback_request_stream = cb; | |
94 | 64 | } |
95 | 65 | |
96 | -int RTPReceiver::ps_demuxer_thread_(void* param) | |
97 | -{ | |
98 | - if (!param) | |
99 | - { | |
100 | - return -1; | |
101 | - } | |
102 | - | |
103 | - RTPReceiver* self = (RTPReceiver*)param; | |
104 | - return self->OnPsProcess(); | |
105 | -} | |
106 | - | |
107 | -int RTPReceiver::ps_decode_thread_(void* param) | |
108 | -{ | |
109 | - if (!param) | |
110 | - { | |
111 | - return -1; | |
112 | - } | |
113 | - | |
114 | - RTPReceiver* self = (RTPReceiver*)param; | |
115 | - return self->OnDecodeProcess(); | |
116 | -} | |
117 | - | |
118 | -bool RTPReceiver::Open(uint16_t localPort) | |
119 | -{ | |
120 | - LOG_INFO("--2---RTPReceiver::Open--{}", m_deviceID); | |
121 | - m_localPort = localPort; | |
122 | - | |
123 | - RTPSessionParams sessparams; | |
124 | - sessparams.SetUsePollThread(true); | |
125 | - sessparams.SetMinimumRTCPTransmissionInterval(10); | |
126 | - sessparams.SetOwnTimestampUnit(1.0/90000.0); | |
127 | - sessparams.SetAcceptOwnPackets(true); | |
128 | - | |
129 | - RTPUDPv4TransmissionParams transparams; | |
130 | - transparams.SetPortbase(m_localPort); | |
131 | - transparams.SetRTPReceiveBuffer(kRtpRecvBufferSize); | |
132 | - cout << "port: " << m_localPort << endl; | |
133 | - LOG_INFO("--3---RTPReceiver::Open--{}", m_deviceID); | |
134 | - | |
135 | - int err = m_rtpSession.Create(sessparams, &transparams); | |
136 | - LOG_INFO("--4---RTPReceiver::Open--{}", m_deviceID); | |
137 | - if (err != 0) | |
138 | - { | |
139 | - LOG_INFO("RTPReceiver::Open m_rtpSession.Create error: {}--{}", err, m_deviceID); | |
140 | - return false; | |
141 | - } | |
142 | - LOG_INFO("--5---RTPReceiver::Open--{}", m_deviceID); | |
66 | +int RTPReceiver::InitPS(){ | |
67 | + | |
143 | 68 | m_psParser.SetReceiveFunction(ReceivePESFunction, this); |
144 | 69 | |
145 | - m_bOpened = true; | |
146 | - LOG_INFO("RTPReceiver::Open ok--{}", m_deviceID); | |
147 | - | |
148 | - LOG_INFO("--1---RTPReceiver::Open--{}", m_deviceID); | |
149 | - m_rtpThread = std::thread(rtp_revc_thread_, this); | |
150 | - m_psThread = std::thread(ps_demuxer_thread_, this); | |
70 | + m_psThreadPtr = new std::thread(ps_demuxer_thread_, this); | |
71 | + if(nullptr == m_psThreadPtr){ | |
72 | + return -1; | |
73 | + } | |
151 | 74 | |
152 | - return true; | |
153 | -} | |
75 | + LOG_INFO("[{}] InitPS finished", m_deviceID); | |
154 | 76 | |
155 | -bool RTPReceiver::IsOpened() const | |
156 | -{ | |
157 | - return m_bOpened; | |
77 | + return 0; | |
158 | 78 | } |
159 | 79 | |
160 | -void RTPReceiver::Close() | |
161 | -{ | |
162 | - m_bRtpExit = true; | |
80 | +void RTPReceiver::ClosePsThread(){ | |
81 | + LOG_INFO("[{}] 3.", m_deviceID); | |
163 | 82 | m_bPsExit = true; |
164 | - | |
165 | - // rtp接收线程退出 | |
166 | - if (m_rtpThread.joinable()) | |
167 | - { | |
168 | - m_rtpThread.join(); | |
169 | - } | |
170 | - m_rtpSession.Destroy(); | |
171 | - LOG_INFO("--2---RTPReceiver::Close rtp recv thread quit --{}", m_deviceID); | |
172 | - | |
173 | 83 | // PS解包线程退出 |
174 | - if (m_psThread.joinable()) | |
84 | + if (m_psThreadPtr->joinable()) | |
175 | 85 | { |
176 | - m_psThread.join(); | |
86 | + m_psThreadPtr->join(); | |
87 | + delete m_psThreadPtr; | |
88 | + m_psThreadPtr = nullptr; | |
177 | 89 | } |
178 | - LOG_INFO("--3---RTPReceiver::Close ps demux thread quit--{}", m_deviceID); | |
179 | - | |
180 | - m_bOpened = false; | |
181 | -} | |
182 | - | |
183 | -int RTPReceiver::GetPsFrameListSize() | |
184 | -{ | |
185 | - std::lock_guard<std::mutex> l(m_psFrameMutex); | |
186 | - return m_psVideoFrames.size(); | |
187 | -} | |
188 | - | |
189 | -void RTPReceiver::ClearPsVideoFrameList() | |
190 | -{ | |
191 | - std::lock_guard<std::mutex> l(m_psFrameMutex); | |
192 | - while (!m_psVideoFrames.empty()) { | |
193 | - Frame* f = m_psVideoFrames.front(); | |
194 | - delete f; | |
195 | - m_psVideoFrames.pop(); | |
196 | - } | |
197 | - LOG_INFO("---->cleared ps video frame list!<----{}", m_deviceID); | |
198 | -} | |
199 | - | |
200 | -// 收RTP包线程 | |
201 | -int RTPReceiver::OnRtpRecv() | |
202 | -{ | |
203 | - uint32_t lastPts = 0; | |
204 | - uint64_t last_recv_ts{0}; | |
205 | - int offset = 0; | |
206 | - int mark = 0; | |
207 | - BYTE* recvTmpBuf = new BYTE[kVideoFrameSize]; | |
208 | - while (!m_bRtpExit) | |
209 | - { | |
210 | - //try | |
211 | - //{ | |
212 | - m_rtpSession.Poll(); | |
213 | - m_rtpSession.BeginDataAccess(); | |
214 | - if (m_rtpSession.GotoFirstSourceWithData()) | |
215 | - { | |
216 | - last_recv_ts = get_cur_time(); | |
217 | - m_idleCount = 0; | |
218 | - m_noDataCount = 0; | |
219 | - do | |
220 | - { | |
221 | - RTPPacket* packet; | |
222 | - while ((packet = m_rtpSession.GetNextPacket()) != NULL/* && !mark*/) | |
223 | - { | |
224 | - do { | |
225 | - if (0 == packet->GetPayloadType()) | |
226 | - { | |
227 | - // 音频数据, 暂不处理 | |
228 | - break; // goto skip_this_packet; | |
229 | - } | |
230 | - | |
231 | - // 判断是否收到完整的帧(有些厂商打的marker标记不准, 所以只能看时间戳来判断) | |
232 | - uint32_t curPts = packet->GetTimestamp(); | |
233 | - if (lastPts != 0 && curPts != lastPts) { | |
234 | - mark = 1; | |
235 | - } | |
236 | - lastPts = curPts; | |
237 | - | |
238 | - int payloadLen = packet->GetPayloadLength(); | |
239 | - if (offset + payloadLen > kVideoFrameSize) | |
240 | - { | |
241 | - offset = 0, mark = 0; | |
242 | - break; // goto skip_this_packet; | |
243 | - } | |
244 | - | |
245 | - if (mark) | |
246 | - { | |
247 | - BYTE* frameBuf = (BYTE*)malloc(sizeof(BYTE) * offset); | |
248 | - if (!frameBuf) { | |
249 | - offset = 0, mark = 0; | |
250 | - break; // goto skip_this_packet; | |
251 | - } | |
252 | - memcpy(frameBuf, recvTmpBuf, offset); | |
253 | - if (!m_bPsExit) | |
254 | - { | |
255 | - std::lock_guard<std::mutex> l(m_psFrameMutex); | |
256 | - if (m_psVideoFrames.size() < 100) | |
257 | - { | |
258 | - m_psVideoFrames.push(new Frame(frameBuf, offset, false)); | |
259 | - } | |
260 | - else { | |
261 | - free(frameBuf); | |
262 | - } | |
263 | - } | |
264 | - else | |
265 | - { | |
266 | - //若此时解码线程已经退出,不再往m_psVideoFrames推送帧,且退出当前线程 | |
267 | - free(frameBuf); | |
268 | - LOG_INFO("OnPsProcess quit, device_id:{}", m_deviceID); | |
269 | - //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "recv video stream interruption!"); | |
270 | - } | |
271 | - offset = 0; | |
272 | - mark = 0; | |
273 | - } | |
274 | - | |
275 | - memcpy(recvTmpBuf + offset, packet->GetPayloadData(), payloadLen); | |
276 | - offset += payloadLen; | |
277 | - } while (0); | |
278 | - //skip_this_packet: | |
279 | - m_rtpSession.DeletePacket(packet); | |
280 | - } | |
281 | - } while (m_rtpSession.GotoNextSourceWithData()); | |
282 | - } | |
283 | - //else { | |
284 | - // if (m_idleCount != -1) | |
285 | - // { | |
286 | - // ++m_idleCount;//流中断计数 | |
287 | - // } | |
288 | - // if (m_noDataCount != 0) | |
289 | - // { | |
290 | - // --m_noDataCount;//没流计数 | |
291 | - // } | |
292 | - // //if (m_idleCount > 3000) { | |
293 | - // // m_hVodEndFunc(m_usrParam); | |
294 | - // // m_idleCount = 0; | |
295 | - // //历史流结束的时候,也会出现超时,这个是正常的 | |
296 | - // if(m_usrParam && ((VideoSession *)GetUsrParam())->video_type() == VideoType::ERECORD) | |
297 | - // { | |
298 | - // if (m_idleCount > 10000) | |
299 | - // { | |
300 | - // //这里要判断下历史流是否结束,如果未结束,就设置为流中断 | |
301 | - // //由于record_stream_status这个函数返回值不准确,所以增加一个进度条大于80% | |
302 | - // if(record_stream_status(((VideoSession *)GetUsrParam())->streamHandle())) | |
303 | - // { | |
304 | - // LOG_INFO("************Record stream is finished**{}**m_progress = {}********", m_deviceID, ((VideoSession *)GetUsrParam())->progress()); | |
305 | - // m_idleCount = -1; | |
306 | - // m_hVodEndFunc(m_usrParam); | |
307 | - // record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle()); | |
308 | - // ((VideoSession *)GetUsrParam())->streamHandle().clear(); | |
309 | - // } | |
310 | - // else | |
311 | - // { | |
312 | - // //如果此时进度大于80% 算完成吧 | |
313 | - // if(((VideoSession *)GetUsrParam())->progress() > 0.80) | |
314 | - // { | |
315 | - // LOG_INFO("************Record stream is overtime**{}**m_progress = {}********", m_deviceID, ((VideoSession *)GetUsrParam())->progress()); | |
316 | - | |
317 | - // m_idleCount = 0; | |
318 | - // m_hVodEndFunc(m_usrParam); | |
319 | - // record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle()); | |
320 | - // ((VideoSession *)GetUsrParam())->streamHandle().clear(); | |
321 | - // } | |
322 | - // else | |
323 | - // { | |
324 | - // m_idleCount = -1; | |
325 | - // //LOG_ERROR("************post ERROR_REALSTREAM_INTERRUPT to structure****{}********", m_deviceID); | |
326 | - // //发送流中断 | |
327 | - // //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Record time video streaming interruption!"); | |
328 | - // } | |
329 | - // } | |
330 | - // | |
331 | - // | |
332 | - // } | |
333 | - // | |
334 | - // if (m_noDataCount < -200000)//任务开始时没收到流 | |
335 | - // { | |
336 | - // //LOG_ERROR("************m_hVodEndFunc(m_usrParam)!!!m_hVodEndFunc(m_usrParam)********{}******", m_deviceID); | |
337 | - // m_noDataCount = -1; | |
338 | - | |
339 | - // //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Record time video streaming interruption2!"); | |
340 | - // //m_hVodEndFunc(m_usrParam); | |
341 | - // } | |
342 | - // } | |
343 | - // else//实时任务断流 | |
344 | - // //if (m_usrParam && ((VideoSession *)GetUsrParam())->video_type() == VideoType::EREAL) | |
345 | - // { | |
346 | - // | |
347 | - // //每超过3000次,发送一次send_vedio_eof 时长大约1.5s | |
348 | - // //若是30000,时长大约 18s | |
349 | - // if(m_idleCount > 30000) | |
350 | - // { | |
351 | - // uint64_t cts = get_cur_time(); | |
352 | - // float duration_not_recv = (cts - last_recv_ts) / 1000.0; | |
353 | - // | |
354 | - // //LOG_ERROR("************I haven't got stream from hik gateway exceed {}s,send eof********{}******", duration_not_recv, m_deviceID); | |
355 | - // m_idleCount = -1; | |
356 | - | |
357 | - // //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption!"); | |
358 | - // } | |
359 | - // | |
360 | - // if (m_noDataCount < -200000)//任务开始时没收到流 | |
361 | - // { | |
362 | - // //LOG_ERROR("************m_noDataCount < -200000********{}******", m_deviceID); | |
363 | - // m_noDataCount = -1; | |
364 | - | |
365 | - // //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption2!"); | |
366 | - // } | |
367 | - // | |
368 | - // } | |
369 | - //} | |
370 | - //} | |
371 | - // catch (GeneralException2& e) | |
372 | - //{ | |
373 | - // //LOG_ERROR("---> video streaming interruption!<---{}, error: {}", m_deviceID, e.err_msg()); | |
374 | - | |
375 | - // byte_buffer bb(64); | |
376 | - // bb << VasCmd::VAS_CMD_REALSTREAM_INTERRUPT << e.err_msg(); | |
377 | - | |
378 | - // if (m_usrParam) | |
379 | - // { | |
380 | - // if (((VideoSession *)GetUsrParam())->msgChan()->is_valid()) { | |
381 | - // try { | |
382 | - // ((VideoSession *)GetUsrParam())->msgChan()->send_msg(bb.data_ptr(), bb.data_size()); | |
383 | - // } | |
384 | - // catch (GeneralException2& e) { | |
385 | - // //LOG_ERROR("[{}] send vas cmd VAS_CMD_REALSTREAM_INTERRUPT error: {}, {}", m_deviceID, e.err_code(), e.err_str()); | |
386 | - // } | |
387 | - // } | |
388 | - | |
389 | - // //通知网关关闭句柄 | |
390 | - // if(!((VideoSession *)GetUsrParam())->streamHandle().empty()) | |
391 | - // { | |
392 | - | |
393 | - // LOG_INFO("---->Notify hisense gateway release handle = {} !<----{}", ((VideoSession *)GetUsrParam())->streamHandle().c_str(), m_deviceID); | |
394 | - // if (((VideoSession *)GetUsrParam())->video_type() == VideoType::EREAL) | |
395 | - // real_stream_stop(((VideoSession *)GetUsrParam())->streamHandle()); | |
396 | - // | |
397 | - // if (((VideoSession *)GetUsrParam())->video_type() == VideoType::ERECORD) | |
398 | - // record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle()); | |
399 | - // | |
400 | - // //清理保活的句柄 | |
401 | - // ((VideoSession *)GetUsrParam())->streamHandle().clear(); | |
402 | - // } | |
403 | - // } | |
404 | - // | |
405 | - // bb.bset(0); | |
406 | - // | |
407 | - //} | |
408 | - m_rtpSession.EndDataAccess(); | |
409 | - RTPTime::Wait(RTPTime(0, 500)); | |
410 | - } | |
411 | - | |
412 | - delete [] recvTmpBuf; | |
413 | - | |
414 | - return 0; | |
415 | -} | |
416 | - | |
417 | -// 解PS包线程 | |
418 | -int RTPReceiver::OnPsProcess() | |
419 | -{ | |
420 | - while (!m_bPsExit) { | |
421 | - m_psFrameMutex.lock(); | |
422 | - if (m_psVideoFrames.size() <= 0){ | |
423 | - m_psFrameMutex.unlock(); | |
424 | - std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
425 | - continue; | |
426 | - } | |
427 | - Frame* frame = m_psVideoFrames.front(); | |
428 | - m_psVideoFrames.pop(); | |
429 | - m_psFrameMutex.unlock(); | |
430 | - if (frame != nullptr) | |
431 | - { | |
432 | - int nRet = m_psParser.AddData(frame->buf_, frame->len_); | |
433 | - if (nRet == -1) | |
434 | - { | |
435 | - LOG_INFO("m_psParser return -1--{}", m_deviceID); | |
436 | - } | |
437 | - else if (nRet == -2) | |
438 | - { | |
439 | - LOG_INFO("m_psParser return -2--{}", m_deviceID); | |
440 | - } | |
441 | - else if (nRet == -3) | |
442 | - { | |
443 | - LOG_INFO("m_psParser return -3--{}", m_deviceID); | |
444 | - } | |
445 | - | |
446 | - delete frame; | |
447 | - frame = nullptr; | |
448 | - } | |
449 | - | |
450 | - } | |
451 | - | |
452 | - ClearPsVideoFrameList(); | |
453 | - | |
454 | - return 0; | |
90 | + | |
91 | + LOG_INFO("[{}] ps demux thread quit", m_deviceID); | |
455 | 92 | } |
456 | 93 | |
457 | 94 | // 处理去除了PS头的数据 |
... | ... | @@ -531,7 +168,129 @@ void RTPReceiver::OnPsDemux(unsigned char streamId, BYTE *data, int len, bool ke |
531 | 168 | m_SliceBuf.add((char*)data, len); |
532 | 169 | } |
533 | 170 | |
534 | -int RTPReceiver::OnDecodeProcess() | |
171 | +// 解PS包线程 | |
172 | +int RTPReceiver::OnPsProcess() | |
535 | 173 | { |
174 | + LOG_INFO("[{}] started.", m_deviceID); | |
175 | + while (!m_bPsExit) { | |
176 | + m_psFrameMutex.lock(); | |
177 | + LOG_DEBUG("[{}] PS frame size : {}", m_deviceID, m_psVideoFrames.size()); | |
178 | + if (m_psVideoFrames.size() <= 0){ | |
179 | + m_psFrameMutex.unlock(); | |
180 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
181 | + continue; | |
182 | + } | |
183 | + Frame* frame = m_psVideoFrames.front(); | |
184 | + m_psVideoFrames.pop(); | |
185 | + m_psFrameMutex.unlock(); | |
186 | + if (frame != nullptr) | |
187 | + { | |
188 | + int nRet = m_psParser.AddData(frame->buf_, frame->len_); | |
189 | + if (nRet == -1) | |
190 | + { | |
191 | + LOG_INFO("m_psParser return -1--{}", m_deviceID); | |
192 | + } | |
193 | + else if (nRet == -2) | |
194 | + { | |
195 | + LOG_INFO("m_psParser return -2--{}", m_deviceID); | |
196 | + } | |
197 | + else if (nRet == -3) | |
198 | + { | |
199 | + LOG_INFO("m_psParser return -3--{}", m_deviceID); | |
200 | + } | |
201 | + | |
202 | + delete frame; | |
203 | + frame = nullptr; | |
204 | + } | |
205 | + } | |
206 | + | |
207 | + ClearPsVideoFrameList(); | |
208 | + | |
209 | + m_hVodEndFunc(m_usrParam); | |
210 | + | |
211 | + LOG_INFO("[{}] exited.", m_deviceID); | |
212 | + | |
536 | 213 | return 0; |
537 | 214 | } |
215 | + | |
216 | +void RTPReceiver::SetDeviceID(string deviceID){ | |
217 | + m_deviceID = deviceID; | |
218 | +} | |
219 | + | |
220 | +int RTPReceiver::GetPsFrameListSize() | |
221 | +{ | |
222 | + std::lock_guard<std::mutex> l(m_psFrameMutex); | |
223 | + return m_psVideoFrames.size(); | |
224 | +} | |
225 | + | |
226 | +void RTPReceiver::ClearPsVideoFrameList() | |
227 | +{ | |
228 | + std::lock_guard<std::mutex> l(m_psFrameMutex); | |
229 | + while (!m_psVideoFrames.empty()) { | |
230 | + Frame* f = m_psVideoFrames.front(); | |
231 | + delete f; | |
232 | + m_psVideoFrames.pop(); | |
233 | + } | |
234 | + LOG_INFO("[{}] cleared ps video frame list!", m_deviceID); | |
235 | +} | |
236 | + | |
237 | +int RTPReceiver::ParsePacket(RTPPacket* packet){ | |
238 | + do { | |
239 | + | |
240 | + if (0 == packet->GetPayloadType()) | |
241 | + { | |
242 | + // 音频数据, 暂不处理 | |
243 | + break; | |
244 | + } | |
245 | + | |
246 | + // 判断是否收到完整的帧(有些厂商打的marker标记不准, 所以只能看时间戳来判断) | |
247 | + uint32_t curPts = packet->GetTimestamp(); | |
248 | + if (lastPts != 0 && curPts != lastPts) { | |
249 | + mark = 1; | |
250 | + } | |
251 | + lastPts = curPts; | |
252 | + | |
253 | + int payloadLen = packet->GetPayloadLength(); | |
254 | + if (offset + payloadLen > kVideoFrameSize) | |
255 | + { | |
256 | + offset = 0, mark = 0; | |
257 | + break; | |
258 | + } | |
259 | + | |
260 | + LOG_DEBUG("[{}] ParsePacket GetPayloadLength", m_deviceID); | |
261 | + | |
262 | + if (mark) | |
263 | + { | |
264 | + BYTE* frameBuf = (BYTE*)malloc(sizeof(BYTE) * offset); | |
265 | + if (!frameBuf) { | |
266 | + offset = 0, mark = 0; | |
267 | + break; | |
268 | + } | |
269 | + memcpy(frameBuf, recvTmpBuf, offset); | |
270 | + if (!m_bPsExit){ | |
271 | + std::lock_guard<std::mutex> l(m_psFrameMutex); | |
272 | + if (m_psVideoFrames.size() < 100) | |
273 | + { | |
274 | + LOG_DEBUG("[{}]ParsePacket push", m_deviceID); | |
275 | + m_psVideoFrames.push(new Frame(frameBuf, offset, false)); | |
276 | + } | |
277 | + else { | |
278 | + free(frameBuf); | |
279 | + } | |
280 | + } | |
281 | + else{ | |
282 | + //若此时解码线程已经退出,不再往m_psVideoFrames推送帧,且退出当前线程 | |
283 | + free(frameBuf); | |
284 | + LOG_INFO("ParsePacket quit, device_id:{}", m_deviceID); | |
285 | + return 1; | |
286 | + } | |
287 | + offset = 0; | |
288 | + mark = 0; | |
289 | + } | |
290 | + | |
291 | + memcpy(recvTmpBuf + offset, packet->GetPayloadData(), payloadLen); | |
292 | + offset += payloadLen; | |
293 | + } while (0); | |
294 | + | |
295 | + return 0; | |
296 | +} | |
538 | 297 | \ No newline at end of file | ... | ... |
src/gb28181/RTPReceiver.h
1 | -#ifndef _RTP_RECEIVER_H_ | |
2 | -#define _RTP_RECEIVER_H_ | |
3 | - | |
4 | - | |
5 | -#include "demuxer.h" | |
6 | -#include "buffer.h" | |
7 | - | |
8 | - | |
9 | -#include "rtpudpv4transmitter.h" | |
10 | -#include "rtpipv4address.h" | |
11 | -#include "rtpsessionparams.h" | |
12 | -#include "rtpsession.h" | |
13 | -#include "rtppacket.h" | |
14 | -#include <queue> | |
15 | -#include <iostream> | |
16 | -#include <atomic> | |
17 | -#include <thread> | |
18 | -#include <string> | |
19 | -#include <mutex> | |
20 | - | |
21 | - | |
22 | -#define OUTTIME_RTCP 30*1000 | |
23 | -#define PAYLOAD 99 | |
24 | -#define PAYLOAD_PS 96 | |
25 | -#define PAYLOAD_H264 98 | |
26 | -#define PAYLOAD_MP4 97 | |
27 | - | |
28 | -#define UDP_SIZE 1400 | |
29 | -#define MIN_PORT 10000 | |
30 | -#define MAX_PORT 60000 | |
31 | -#define RTP_MAX_PACKET_LEN 1450 | |
32 | - | |
33 | -using namespace jrtplib; | |
34 | -using namespace std; | |
35 | - | |
36 | -typedef unsigned char BYTE; | |
37 | - | |
38 | -/** 视频数据回调 | |
39 | -* | |
40 | -* @param videoType [in] 视频类型 音频-0xC0、h264-0x1B、MPEG4-0x01、SVAC-0x80 | |
41 | -* @param data [in] 视频数据 | |
42 | -* @param len [in] 视频数据长度 | |
43 | -* @param isKey [in] 是否为关键帧 | |
44 | -* @param pts [in] 时间戳 | |
45 | -*/ | |
46 | -typedef void(*CallBack_Stream)(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts); | |
47 | - | |
48 | -/** 录像回放完成回调消息通知 | |
49 | -*/ | |
50 | -typedef void(*CallBack_VodFileEnd)(void* userdata); | |
51 | - | |
52 | -int AllocRtpPort(void); | |
53 | - | |
54 | -class MyRTPSession : public RTPSession | |
55 | -{ | |
56 | -public: | |
57 | - MyRTPSession() {} | |
58 | - virtual ~MyRTPSession() {} | |
59 | - | |
60 | -private: | |
61 | - virtual void OnRTPPacket(RTPPacket* pack, const RTPTime& receiverTime, const RTPAddress* senderAddress) | |
62 | - { | |
63 | - AddDestination(*senderAddress); | |
64 | - } | |
65 | - | |
66 | - virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack, const RTPTime &receivetime,const RTPAddress *senderaddress) | |
67 | - { | |
68 | - //AddDestination(*senderaddress); | |
69 | - //const char* name = "hi~"; | |
70 | - //SendRTCPAPPPacket(0, (const uint8_t*)name, "keeplive", 8); | |
71 | - | |
72 | - //printf("send rtcp app"); | |
73 | - } | |
74 | -}; | |
75 | - | |
76 | -// 标识帧, 注意buffer需要自己开辟和释放 | |
77 | -struct Frame { | |
78 | - Frame() { buf_ = NULL; len_ = 0; } | |
79 | - ~Frame() { | |
80 | - if (buf_ != nullptr) | |
81 | - { | |
82 | - free(buf_); | |
83 | - buf_ = nullptr; | |
84 | - } | |
85 | - } | |
86 | - Frame(BYTE* buf, int len, bool key) : buf_(buf), len_(len), key_(key) {} | |
87 | - BYTE* buf_; | |
88 | - int len_; | |
89 | - bool key_{}; | |
90 | -}; | |
91 | - | |
92 | -class FrameToDecode | |
93 | -{ | |
94 | -public: | |
95 | - FrameToDecode() | |
96 | - : m_SliceBuf(0) | |
97 | - , m_localPts(0) | |
98 | - , m_LastPTS(-1) | |
99 | - , m_LastIsKeyFrame(0) {} | |
100 | - FrameToDecode(unsigned char m_streamId) | |
101 | - : m_SliceBuf(0) | |
102 | - , m_localPts(0) | |
103 | - , m_LastPTS(-1) | |
104 | - , m_LastIsKeyFrame(0) | |
105 | - , m_streamId (m_streamId) {} | |
106 | - | |
107 | - void operator=(FrameToDecode &temp) | |
108 | - { | |
109 | - m_SliceBuf = temp.m_SliceBuf; | |
110 | - m_streamId = temp.m_streamId; | |
111 | - m_localPts = temp.m_localPts; | |
112 | - m_LastPTS = temp.m_LastPTS; | |
113 | - m_LastIsKeyFrame = temp.m_LastIsKeyFrame; | |
114 | - } | |
115 | - | |
116 | - CBuffer m_SliceBuf; | |
117 | - unsigned char m_streamId{}; | |
118 | - uint64_t m_localPts; | |
119 | - uint64_t m_LastPTS; | |
120 | - bool m_LastIsKeyFrame; | |
121 | -}; | |
122 | - | |
123 | - | |
124 | -class RTPReceiver | |
125 | -{ | |
126 | - RTPReceiver(const RTPReceiver& other); | |
127 | - RTPReceiver& operator= (const RTPReceiver& other); | |
128 | - | |
129 | -public: | |
130 | - RTPReceiver(); | |
131 | - ~RTPReceiver(); | |
132 | - | |
133 | - bool Open(uint16_t localPort); | |
134 | - bool IsOpened() const; | |
135 | - void Close(); | |
136 | - | |
137 | - int GetPsFrameListSize(); | |
138 | - void ClearPsVideoFrameList(); | |
139 | - | |
140 | - void OnPsDemux(unsigned char streamId, BYTE *data, int len, bool key, uint64_t pts, uint64_t localPts); | |
141 | - | |
142 | - void SetOutputCallback(CallBack_Stream cb, void* param); | |
143 | - void SetVodEndCallback(CallBack_VodFileEnd cb, void* param); | |
144 | - CallBack_VodFileEnd GetVodEndFunc(){ return m_hVodEndFunc; } | |
145 | - | |
146 | - void *GetUsrParam(){ return m_usrParam; } | |
147 | - void SetDeviceID(string deviceID){this->m_deviceID = deviceID; } | |
148 | - | |
149 | -private: | |
150 | - static int rtp_revc_thread_(void* param); | |
151 | - static int ps_demuxer_thread_(void* param); | |
152 | - static int ps_decode_thread_(void* param); | |
153 | - | |
154 | - int OnRtpRecv(); | |
155 | - int OnPsProcess(); | |
156 | - int OnDecodeProcess(); | |
157 | - | |
158 | -private: | |
159 | - std::thread m_rtpThread; // RTP接收线程 | |
160 | - std::thread m_psThread; // PS解包线程 | |
161 | - | |
162 | - uint16_t m_localPort; // RTP接收端口 | |
163 | - MyRTPSession m_rtpSession; // RTP会话 | |
164 | - std::atomic_bool m_bRtpExit; // 标识RTP收包线程闭 | |
165 | - std::atomic_bool m_bPsExit; // 标识PS解包线程关闭 | |
166 | - std::queue<Frame*> m_psVideoFrames; | |
167 | - mutex m_psFrameMutex; | |
168 | - | |
169 | - CMpeg2Demux m_psParser; | |
170 | - | |
171 | - void* m_usrParam; | |
172 | - std::atomic_bool m_bOpened; | |
173 | - | |
174 | - CallBack_Stream m_h264DataFunc; // 视频流回调 | |
175 | - CallBack_VodFileEnd m_hVodEndFunc; // 录像流结束回调 | |
176 | - | |
177 | - CBuffer m_SliceBuf; | |
178 | - uint64_t m_LastPTS; | |
179 | - bool m_LastIsKeyFrame; | |
180 | - unsigned char m_LastStreamType; | |
181 | - int64_t m_idleCount; | |
182 | - int64_t m_noDataCount;//线程计数,用于打开流成功但是实际没流过来 | |
183 | - | |
184 | - string m_deviceID; | |
185 | - int64_t m_notToDecodCount{0};//线程计数,用来代表多长时间没有调用解码回调,针对大华相机 | |
186 | -}; | |
187 | - | |
188 | -#endif // _RTP_RECEIVER_H_ | |
1 | +#ifndef _RTP_RECEIVER_H_ | |
2 | +#define _RTP_RECEIVER_H_ | |
3 | + | |
4 | +#include "buffer.h" | |
5 | +#include "demuxer.h" | |
6 | +#include "rtppacket.h" | |
7 | +#include <stdint.h> | |
8 | +#include <mutex> | |
9 | +#include <queue> | |
10 | +#include <atomic> | |
11 | +#include <thread> | |
12 | + | |
13 | +typedef unsigned char BYTE; | |
14 | + | |
15 | +using namespace jrtplib; | |
16 | +using namespace std; | |
17 | + | |
18 | +/** 视频数据回调 | |
19 | +* | |
20 | +* @param videoType [in] 视频类型 音频-0xC0、h264-0x1B、MPEG4-0x01、SVAC-0x80 | |
21 | +* @param data [in] 视频数据 | |
22 | +* @param len [in] 视频数据长度 | |
23 | +* @param isKey [in] 是否为关键帧 | |
24 | +* @param pts [in] 时间戳 | |
25 | +*/ | |
26 | +typedef void(*CallBack_Stream)(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts); | |
27 | + | |
28 | +/** 录像回放完成回调消息通知 | |
29 | +*/ | |
30 | +typedef void(*CallBack_VodFileEnd)(void* userdata); | |
31 | + | |
32 | +/** | |
33 | + * 请求流 | |
34 | +*/ | |
35 | +typedef bool(*CallBack_Request_Stream)(); | |
36 | + | |
37 | +// 标识帧, 注意buffer需要自己开辟和释放 | |
38 | +struct Frame { | |
39 | + Frame() { buf_ = NULL; len_ = 0; } | |
40 | + ~Frame() { | |
41 | + if (buf_ != nullptr) | |
42 | + { | |
43 | + free(buf_); | |
44 | + buf_ = nullptr; | |
45 | + } | |
46 | + } | |
47 | + Frame(BYTE* buf, int len, bool key) : buf_(buf), len_(len), key_(key) {} | |
48 | + BYTE* buf_; | |
49 | + int len_; | |
50 | + bool key_{}; | |
51 | +}; | |
52 | + | |
53 | +class FrameToDecode | |
54 | +{ | |
55 | +public: | |
56 | + FrameToDecode() | |
57 | + : m_SliceBuf(0) | |
58 | + , m_localPts(0) | |
59 | + , m_LastPTS(-1) | |
60 | + , m_LastIsKeyFrame(0) {} | |
61 | + FrameToDecode(unsigned char m_streamId) | |
62 | + : m_SliceBuf(0) | |
63 | + , m_localPts(0) | |
64 | + , m_LastPTS(-1) | |
65 | + , m_LastIsKeyFrame(0) | |
66 | + , m_streamId (m_streamId) {} | |
67 | + | |
68 | + void operator=(FrameToDecode &temp) | |
69 | + { | |
70 | + m_SliceBuf = temp.m_SliceBuf; | |
71 | + m_streamId = temp.m_streamId; | |
72 | + m_localPts = temp.m_localPts; | |
73 | + m_LastPTS = temp.m_LastPTS; | |
74 | + m_LastIsKeyFrame = temp.m_LastIsKeyFrame; | |
75 | + } | |
76 | + | |
77 | + CBuffer m_SliceBuf; | |
78 | + unsigned char m_streamId{}; | |
79 | + uint64_t m_localPts; | |
80 | + uint64_t m_LastPTS; | |
81 | + bool m_LastIsKeyFrame; | |
82 | +}; | |
83 | + | |
84 | +class RTPReceiver{ | |
85 | + | |
86 | +public: | |
87 | + RTPReceiver(); | |
88 | + ~RTPReceiver(); | |
89 | + | |
90 | + virtual bool Open(uint16_t localPort) = 0; | |
91 | + virtual bool IsOpened() = 0; | |
92 | + virtual void Close() = 0; | |
93 | + | |
94 | + void SetVodEndCallback(CallBack_VodFileEnd cb, void* param); | |
95 | + | |
96 | + void SetOutputCallback(CallBack_Stream cb, void* param); | |
97 | + | |
98 | + void SetRequestStreamCallback(CallBack_Request_Stream cb); | |
99 | + | |
100 | + void SetDeviceID(string deviceID); | |
101 | + | |
102 | + int GetPsFrameListSize(); | |
103 | + | |
104 | +public: | |
105 | + void OnPsDemux(unsigned char streamId, BYTE *data, int len, bool key, uint64_t pts, uint64_t localPts); | |
106 | + int OnPsProcess(); | |
107 | + void ClearPsVideoFrameList(); | |
108 | + int ParsePacket(RTPPacket* packet); | |
109 | + | |
110 | +public: | |
111 | + int InitPS(); | |
112 | + void ClosePsThread(); | |
113 | + void *GetUsrParam(){ return m_usrParam; } | |
114 | + | |
115 | +public: | |
116 | + CBuffer m_SliceBuf; | |
117 | + uint64_t m_LastPTS; | |
118 | + bool m_LastIsKeyFrame; | |
119 | + unsigned char m_LastStreamType; | |
120 | + | |
121 | + int64_t m_notToDecodCount{0};//线程计数,用来代表多长时间没有调用解码回调,针对大华相机 | |
122 | + | |
123 | + void* m_usrParam; | |
124 | + CallBack_Stream m_h264DataFunc; // 视频流回调 | |
125 | + | |
126 | + std::queue<Frame*> m_psVideoFrames; | |
127 | + mutex m_psFrameMutex; | |
128 | + | |
129 | + string m_deviceID; | |
130 | + | |
131 | + CMpeg2Demux m_psParser; | |
132 | + std::atomic_bool m_bPsExit; // 标识PS解包线程关闭 | |
133 | + | |
134 | + uint32_t lastPts{0}; | |
135 | + uint64_t last_recv_ts{0}; | |
136 | + int offset{0}; | |
137 | + int mark{0}; | |
138 | + BYTE* recvTmpBuf{nullptr}; | |
139 | + | |
140 | + std::thread* m_psThreadPtr; // PS解包线程 | |
141 | + | |
142 | + CallBack_VodFileEnd m_hVodEndFunc; // 录像流结束回调 | |
143 | + CallBack_Request_Stream m_callback_request_stream; //请求流回调 | |
144 | +}; | |
145 | + | |
146 | +#endif // _RTP_RECEIVER_H_ | |
189 | 147 | \ No newline at end of file | ... | ... |
src/gb28181/RTPTcpReceiver.cpp
0 → 100644
1 | +#include"RTPTcpReceiver.h" | |
2 | +#include "../logger.hpp" | |
3 | + | |
4 | + | |
5 | +static long long get_cur_time() { | |
6 | + | |
7 | + chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | |
8 | + = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | |
9 | + | |
10 | + return tpMicro.time_since_epoch().count(); | |
11 | +} | |
12 | + | |
13 | +// class TcpRTPSession : public RTPSession | |
14 | +// { | |
15 | +// public: | |
16 | +// void setReceiver(RTPTcpReceiver* r){ | |
17 | +// tcpReceiver = r; | |
18 | +// } | |
19 | + | |
20 | +// protected: | |
21 | +// void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled) | |
22 | +// { | |
23 | +// // printf("SSRC %x Got packet (%d bytes) in OnValidatedRTPPacket from source 0x%04x!\n", GetLocalSSRC(), | |
24 | +// // (int)rtppack->GetPayloadLength(), srcdat->GetSSRC()); | |
25 | + | |
26 | +// LOG_DEBUG("SSRC {} Got packet ({} bytes) in OnValidatedRTPPacket from source {}}!\n", GetLocalSSRC(), | |
27 | +// (int)rtppack->GetPayloadLength(), srcdat->GetSSRC()); | |
28 | + | |
29 | +// if(nullptr != tcpReceiver){ | |
30 | +// tcpReceiver->ParsePacket(rtppack); | |
31 | +// } | |
32 | +// DeletePacket(rtppack); | |
33 | +// *ispackethandled = true; | |
34 | +// } | |
35 | + | |
36 | +// void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t, const void *itemdata, size_t itemlength) | |
37 | +// { | |
38 | +// char msg[1024]; | |
39 | + | |
40 | +// memset(msg, 0, sizeof(msg)); | |
41 | +// if (itemlength >= sizeof(msg)) | |
42 | +// itemlength = sizeof(msg)-1; | |
43 | + | |
44 | +// memcpy(msg, itemdata, itemlength); | |
45 | +// // printf("SSRC %x Received SDES item (%d): %s from SSRC %x\n", GetLocalSSRC(), (int)t, msg, srcdat->GetSSRC()); | |
46 | +// LOG_DEBUG("SSRC {} Received SDES item ({}): {} from SSRC {}\n", GetLocalSSRC(), (int)t, msg, srcdat->GetSSRC()); | |
47 | +// } | |
48 | + | |
49 | +// private: | |
50 | +// RTPTcpReceiver* tcpReceiver{nullptr}; | |
51 | +// }; | |
52 | + | |
53 | +class MyTCPTransmitter : public RTPTCPTransmitter | |
54 | +{ | |
55 | +public: | |
56 | + void setReceiver(RTPTcpReceiver* r){ | |
57 | + tcpReceiver = r; | |
58 | + } | |
59 | + | |
60 | +public: | |
61 | + MyTCPTransmitter() : RTPTCPTransmitter(0){ } | |
62 | + | |
63 | + void OnSendError(SocketType sock) | |
64 | + { | |
65 | + LOG_ERROR("Error sending over socket {}, removing destination", sock); | |
66 | + DeleteDestination(RTPTCPAddress(sock)); | |
67 | + if(nullptr != tcpReceiver && !tcpReceiver->isClosing()){ | |
68 | + tcpReceiver->RequestStream(); | |
69 | + } | |
70 | + } | |
71 | + | |
72 | + void OnReceiveError(SocketType sock) | |
73 | + { | |
74 | + LOG_ERROR("Error receiving over socket {}, removing destination", sock); | |
75 | + DeleteDestination(RTPTCPAddress(sock)); | |
76 | + } | |
77 | + | |
78 | +private: | |
79 | + RTPTcpReceiver* tcpReceiver{nullptr}; | |
80 | +}; | |
81 | + | |
82 | +static int rtp_revc_thread_(void* param) | |
83 | +{ | |
84 | + if (!param) | |
85 | + { | |
86 | + return -1; | |
87 | + } | |
88 | + | |
89 | + RTPTcpReceiver* self = (RTPTcpReceiver*)param; | |
90 | + return self->OnRtpRecv(); | |
91 | +} | |
92 | + | |
93 | + | |
94 | +RTPTcpReceiver::RTPTcpReceiver() | |
95 | +: m_bRtpExit(false) | |
96 | +, m_bOpened(false) | |
97 | +, m_idleCount(-1) | |
98 | +, m_noDataCount(-1) | |
99 | +, m_nListener(-1) | |
100 | +, m_bAccepted(false) | |
101 | +, m_bClosing(false) | |
102 | +{ | |
103 | + m_rtpSessionPtr = new RTPSession(); | |
104 | + m_pSessparams = new RTPSessionParams(); | |
105 | + m_pTrans = new MyTCPTransmitter(); | |
106 | +} | |
107 | + | |
108 | +RTPTcpReceiver::~RTPTcpReceiver(){ | |
109 | + if (IsOpened()) | |
110 | + Close(); | |
111 | + | |
112 | + if(m_rtpSessionPtr != nullptr){ | |
113 | + delete m_rtpSessionPtr; | |
114 | + m_rtpSessionPtr = nullptr; | |
115 | + } | |
116 | + | |
117 | + if(m_pSessparams != nullptr){ | |
118 | + delete m_pSessparams; | |
119 | + m_pSessparams = nullptr; | |
120 | + } | |
121 | + | |
122 | + if(m_pTrans != nullptr){ | |
123 | + delete m_pTrans; | |
124 | + m_pTrans = nullptr; | |
125 | + } | |
126 | +} | |
127 | + | |
128 | +bool RTPTcpReceiver::Open(uint16_t localPort){ | |
129 | + if(0 != initSession(localPort)){ | |
130 | + return false; | |
131 | + } | |
132 | + | |
133 | + m_bOpened = true; | |
134 | + | |
135 | + LOG_INFO("[{}] started.", m_deviceID); | |
136 | + | |
137 | + return true; | |
138 | +} | |
139 | + | |
140 | +bool RTPTcpReceiver::IsOpened(){ | |
141 | + LOG_INFO("[{}] isopng:{} ", m_deviceID, m_bOpened); | |
142 | + return m_bOpened; | |
143 | +} | |
144 | + | |
145 | +void RTPTcpReceiver::Close(){ | |
146 | + | |
147 | + m_bClosing = true; | |
148 | + | |
149 | + m_bAccepted = true; | |
150 | + m_bRtpExit = true; | |
151 | + | |
152 | + LOG_DEBUG("[{}] 1.", m_deviceID); | |
153 | + | |
154 | + // rtp接收线程退出 | |
155 | + if (m_rtpThread.joinable()) | |
156 | + { | |
157 | + m_rtpThread.join(); | |
158 | + } | |
159 | + | |
160 | + LOG_DEBUG("[{}] 2.", m_deviceID); | |
161 | + | |
162 | + ClosePsThread(); | |
163 | + | |
164 | + m_bOpened = false; | |
165 | + | |
166 | + LOG_INFO("[{}] closed.", m_deviceID); | |
167 | +} | |
168 | + | |
169 | +bool RTPTcpReceiver::isClosing(){ | |
170 | + return m_bClosing; | |
171 | +} | |
172 | + | |
173 | +int RTPTcpReceiver::initSession(int localPort){ | |
174 | + m_nListener = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP); | |
175 | + if (m_nListener < 0) | |
176 | + { | |
177 | + return -1; | |
178 | + } | |
179 | + | |
180 | + sockaddr_in serverAddr; | |
181 | + memset(&serverAddr, 0, sizeof(sockaddr_in)); | |
182 | + serverAddr.sin_family = AF_INET; | |
183 | + serverAddr.sin_port = htons(localPort); | |
184 | + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |
185 | + int nRet = bind(m_nListener, (sockaddr*)&serverAddr, sizeof(serverAddr)); | |
186 | + if (nRet == -1) | |
187 | + { | |
188 | + LOG_ERROR("[{}] 绑定端口失败: {}", m_deviceID, localPort); | |
189 | + return -1; | |
190 | + } | |
191 | + | |
192 | + if (listen(m_nListener, 1) == -1) | |
193 | + { | |
194 | + LOG_ERROR("[{}] listen 失败", m_deviceID); | |
195 | + return -1; | |
196 | + } | |
197 | + | |
198 | + int nPackSize = 45678; | |
199 | + m_pSessparams->SetProbationType(RTPSources::NoProbation); | |
200 | + m_pSessparams->SetOwnTimestampUnit(90000.0 / 25.0); | |
201 | + m_pSessparams->SetMaximumPacketSize(nPackSize + 64); | |
202 | + | |
203 | + int status = m_pTrans->Init(false); | |
204 | + status = m_pTrans->Create(65535, NULL); | |
205 | + m_pTrans->setReceiver(this); | |
206 | + | |
207 | + status = m_rtpSessionPtr->Create(*m_pSessparams, m_pTrans); | |
208 | + if (status < 0) | |
209 | + { | |
210 | + LOG_ERROR("[{}] create session error!!", m_deviceID); | |
211 | + return -1; | |
212 | + } | |
213 | + | |
214 | + m_rtpThread = std::thread(rtp_revc_thread_, this); | |
215 | + | |
216 | + InitPS(); | |
217 | + | |
218 | + bool bRet = RequestStream(); | |
219 | + if (!bRet) | |
220 | + { | |
221 | + LOG_INFO("[{}] 请求流失败!", m_deviceID); | |
222 | + return -1; | |
223 | + } | |
224 | + | |
225 | + LOG_INFO("[{}] 初始化成功, congratulations !!!", m_deviceID); | |
226 | + | |
227 | + return 0; | |
228 | +} | |
229 | + | |
230 | +int RTPTcpReceiver::OnRtpRecv() | |
231 | +{ | |
232 | + if(nullptr == m_rtpSessionPtr){ | |
233 | + return -1; | |
234 | + } | |
235 | + | |
236 | + LOG_INFO("[{}] OnRtpRecv started, m_nListener : {}", m_deviceID, m_nListener); | |
237 | + | |
238 | + sockaddr_in clientAddr; | |
239 | + int nLen = sizeof(sockaddr_in); | |
240 | + SocketType nServer = -1; | |
241 | + | |
242 | + LOG_INFO("[{}] Poll started.", m_deviceID); | |
243 | + int status = -1; | |
244 | + while(!m_bRtpExit){ | |
245 | + while(!m_bAccepted){ | |
246 | + LOG_DEBUG("[{}] accepting...", m_deviceID); | |
247 | + nServer = accept(m_nListener, (sockaddr*)&clientAddr, (socklen_t * ) &nLen); | |
248 | + if (-1 == nServer){ | |
249 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
250 | + continue; | |
251 | + } | |
252 | + m_rtpSessionPtr->AddDestination(RTPTCPAddress(nServer)); | |
253 | + m_bAccepted = true; | |
254 | + | |
255 | + LOG_INFO("[{}] nServer={}", m_deviceID, nServer); | |
256 | + break; | |
257 | + } | |
258 | + | |
259 | + m_rtpSessionPtr->BeginDataAccess(); | |
260 | + if (m_rtpSessionPtr->GotoFirstSourceWithData()) | |
261 | + { | |
262 | + do | |
263 | + { | |
264 | + RTPPacket *pack; | |
265 | + | |
266 | + while ((pack = m_rtpSessionPtr->GetNextPacket()) != NULL) | |
267 | + { | |
268 | + LOG_DEBUG("[{}] time: {} ", m_deviceID, get_cur_time()); | |
269 | + ParsePacket(pack); | |
270 | + | |
271 | + m_rtpSessionPtr->DeletePacket(pack); | |
272 | + } | |
273 | + } while (m_rtpSessionPtr->GotoNextSourceWithData()); | |
274 | + } | |
275 | + | |
276 | + m_rtpSessionPtr->EndDataAccess(); | |
277 | + | |
278 | + m_rtpSessionPtr->Poll(); | |
279 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
280 | + } | |
281 | + | |
282 | + m_rtpSessionPtr->Destroy(); | |
283 | + | |
284 | + if(nServer > 0){ | |
285 | + close(nServer); | |
286 | + } | |
287 | + if(m_nListener > 0){ | |
288 | + close(m_nListener); | |
289 | + } | |
290 | + | |
291 | + LOG_INFO("[{}] OnRtpRecv exited.", m_deviceID); | |
292 | + | |
293 | + return 0; | |
294 | +} | |
295 | + | |
296 | +bool RTPTcpReceiver::RequestStream(){ | |
297 | + bool bConnect = m_callback_request_stream(); | |
298 | + if(!bConnect){ | |
299 | + Close(); | |
300 | + return false; | |
301 | + } | |
302 | + m_bAccepted = false; | |
303 | + | |
304 | + return true; | |
305 | +} | |
0 | 306 | \ No newline at end of file | ... | ... |
src/gb28181/RTPTcpReceiver.h
0 → 100644
1 | +#ifndef _RTP_TCP_RECEIVER_H_ | |
2 | +#define _RTP_TCP_RECEIVER_H_ | |
3 | + | |
4 | + | |
5 | +#include "demuxer.h" | |
6 | +#include "buffer.h" | |
7 | + | |
8 | +#include "rtpsession.h" | |
9 | +#include "rtptcptransmitter.h" | |
10 | +#include "rtpipv4address.h" | |
11 | +#include "rtptcpaddress.h" | |
12 | +#include "rtpsessionparams.h" | |
13 | +#include "rtperrors.h" | |
14 | +#include "rtpsourcedata.h" | |
15 | +#include "rtpsocketutil.h" | |
16 | +#include <stdlib.h> | |
17 | +#include <stdio.h> | |
18 | +#include <iostream> | |
19 | +#include <string> | |
20 | + | |
21 | +#include <queue> | |
22 | +#include <atomic> | |
23 | +#include <thread> | |
24 | +#include <mutex> | |
25 | + | |
26 | +#include "RTPReceiver.h" | |
27 | + | |
28 | + | |
29 | +#define OUTTIME_RTCP 30*1000 | |
30 | +#define PAYLOAD 99 | |
31 | +#define PAYLOAD_PS 96 | |
32 | +#define PAYLOAD_H264 98 | |
33 | +#define PAYLOAD_MP4 97 | |
34 | + | |
35 | +#define UDP_SIZE 1400 | |
36 | +#define MIN_PORT 10000 | |
37 | +#define MAX_PORT 60000 | |
38 | +#define RTP_MAX_PACKET_LEN 1450 | |
39 | + | |
40 | +using namespace jrtplib; | |
41 | +using namespace std; | |
42 | + | |
43 | + | |
44 | + | |
45 | +class TcpRTPSession; | |
46 | +class MyTCPTransmitter; | |
47 | + | |
48 | +class RTPTcpReceiver:public RTPReceiver | |
49 | +{ | |
50 | +public: | |
51 | + RTPTcpReceiver(); | |
52 | + ~RTPTcpReceiver(); | |
53 | + | |
54 | + bool Open(uint16_t localPort); | |
55 | + bool IsOpened(); | |
56 | + void Close(); | |
57 | + | |
58 | +public: | |
59 | + int OnRtpRecv(); | |
60 | + bool RequestStream(); | |
61 | + bool isClosing(); | |
62 | + | |
63 | +private: | |
64 | + int initSession(int localPort); | |
65 | + | |
66 | +private: | |
67 | + | |
68 | + std::atomic_bool m_bRtpExit; // 标识RTP收包线程闭 | |
69 | + | |
70 | + std::atomic_bool m_bOpened; | |
71 | + std::atomic_bool m_bAccepted; | |
72 | + std::atomic_bool m_bClosing; | |
73 | + | |
74 | + int64_t m_idleCount; | |
75 | + int64_t m_noDataCount;//线程计数,用于打开流成功但是实际没流过来 | |
76 | + | |
77 | + std::thread m_rtpThread; // RTP接收线程 | |
78 | + SocketType m_nListener; | |
79 | + | |
80 | + RTPSession* m_rtpSessionPtr; // RTP会话 | |
81 | + RTPSessionParams* m_pSessparams; | |
82 | + MyTCPTransmitter* m_pTrans; | |
83 | +}; | |
84 | + | |
85 | +#endif // _RTP_TCP_RECEIVER_H_ | ... | ... |
src/gb28181/RTPUdpReceiver.cpp
0 → 100644
1 | + | |
2 | +#include "RTPUdpReceiver.h" | |
3 | +#include <iostream> | |
4 | +#include <time.h> | |
5 | + | |
6 | +#include <thread> | |
7 | +#include <chrono> | |
8 | + | |
9 | +#include "../logger.hpp" | |
10 | + | |
11 | +using namespace std; | |
12 | + | |
13 | +#define BUFFERSIZE_1024 4096 | |
14 | +#define BUFFERSIZE_GAP 4096//5120 //1024*5 | |
15 | + | |
16 | +namespace | |
17 | +{ | |
18 | + const int kVideoFrameSize = BUFFERSIZE_1024*BUFFERSIZE_1024*5*2; | |
19 | + const int kRtpRecvBufferSize = BUFFERSIZE_1024*BUFFERSIZE_1024*2; | |
20 | + const uint16_t kInvalidPort = 0; | |
21 | +}; // namespace | |
22 | + | |
23 | +class UdpRTPSession : public RTPSession | |
24 | +{ | |
25 | +public: | |
26 | + UdpRTPSession() {} | |
27 | + virtual ~UdpRTPSession() {} | |
28 | + | |
29 | +private: | |
30 | + virtual void OnRTPPacket(RTPPacket* pack, const RTPTime& receiverTime, const RTPAddress* senderAddress) | |
31 | + { | |
32 | + AddDestination(*senderAddress); | |
33 | + } | |
34 | + | |
35 | + virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack, const RTPTime &receivetime,const RTPAddress *senderaddress) | |
36 | + { | |
37 | + //AddDestination(*senderaddress); | |
38 | + //const char* name = "hi~"; | |
39 | + //SendRTCPAPPPacket(0, (const uint8_t*)name, "keeplive", 8); | |
40 | + | |
41 | + //printf("send rtcp app"); | |
42 | + } | |
43 | +}; | |
44 | + | |
45 | + | |
46 | +static long long get_cur_time() { | |
47 | + | |
48 | + chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro | |
49 | + = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now()); | |
50 | + | |
51 | + return tpMicro.time_since_epoch().count(); | |
52 | +} | |
53 | + | |
54 | +static int rtp_revc_thread_(void* param) | |
55 | +{ | |
56 | + if (!param) | |
57 | + { | |
58 | + return -1; | |
59 | + } | |
60 | + | |
61 | + RTPUdpReceiver* self = (RTPUdpReceiver*)param; | |
62 | + return self->OnRtpRecv(); | |
63 | +} | |
64 | + | |
65 | +RTPUdpReceiver::RTPUdpReceiver() | |
66 | +: m_bRtpExit(false) | |
67 | +, m_bOpened(false) | |
68 | +, m_idleCount(-1) | |
69 | +,m_noDataCount(-1) | |
70 | +{ | |
71 | + m_sessparamsPtr = new RTPSessionParams(); | |
72 | + m_transparamsPtr = new RTPUDPv4TransmissionParams(); | |
73 | + m_rtpSessionPtr = new UdpRTPSession(); | |
74 | +} | |
75 | + | |
76 | +RTPUdpReceiver::~RTPUdpReceiver() | |
77 | +{ | |
78 | + if (IsOpened()) | |
79 | + Close(); | |
80 | + | |
81 | + if(nullptr != m_sessparamsPtr){ | |
82 | + delete m_sessparamsPtr; | |
83 | + m_sessparamsPtr = nullptr; | |
84 | + } | |
85 | + | |
86 | + if(nullptr != m_transparamsPtr){ | |
87 | + delete m_transparamsPtr; | |
88 | + m_transparamsPtr = nullptr; | |
89 | + } | |
90 | + | |
91 | + if(nullptr != m_rtpSessionPtr){ | |
92 | + delete m_rtpSessionPtr; | |
93 | + m_rtpSessionPtr = nullptr; | |
94 | + } | |
95 | +} | |
96 | + | |
97 | +bool RTPUdpReceiver::Open(uint16_t localPort) | |
98 | +{ | |
99 | + m_sessparamsPtr->SetUsePollThread(true); | |
100 | + m_sessparamsPtr->SetMinimumRTCPTransmissionInterval(10); | |
101 | + m_sessparamsPtr->SetOwnTimestampUnit(1.0/90000.0); | |
102 | + m_sessparamsPtr->SetAcceptOwnPackets(true); | |
103 | + | |
104 | + m_transparamsPtr->SetPortbase(localPort); | |
105 | + m_transparamsPtr->SetRTPReceiveBuffer(kRtpRecvBufferSize); | |
106 | + | |
107 | + LOG_INFO("[{}] port: {}", m_deviceID, localPort); | |
108 | + | |
109 | + int err = m_rtpSessionPtr->Create(*m_sessparamsPtr, m_transparamsPtr); | |
110 | + if (err != 0) | |
111 | + { | |
112 | + LOG_ERROR("[{}] Create error: {}", m_deviceID, err); | |
113 | + return false; | |
114 | + } | |
115 | + | |
116 | + m_rtpThreadPtr = new std::thread(rtp_revc_thread_, this); | |
117 | + if (nullptr == m_rtpThreadPtr) | |
118 | + { | |
119 | + LOG_ERROR("[{}] Create m_rtpThreadPtr error", m_deviceID); | |
120 | + return false; | |
121 | + } | |
122 | + | |
123 | + | |
124 | + if (InitPS() != 0) | |
125 | + { | |
126 | + return false; | |
127 | + } | |
128 | + | |
129 | + m_bOpened = true; | |
130 | + LOG_INFO("[{}] Open ok", m_deviceID); | |
131 | + | |
132 | + return true; | |
133 | +} | |
134 | + | |
135 | +bool RTPUdpReceiver::IsOpened() | |
136 | +{ | |
137 | + return m_bOpened; | |
138 | +} | |
139 | + | |
140 | +void RTPUdpReceiver::Close() | |
141 | +{ | |
142 | + m_bRtpExit = true; | |
143 | + | |
144 | + // rtp接收线程退出 | |
145 | + if (nullptr != m_rtpThreadPtr && m_rtpThreadPtr->joinable()) | |
146 | + { | |
147 | + m_rtpThreadPtr->join(); | |
148 | + delete m_rtpThreadPtr; | |
149 | + m_rtpThreadPtr = nullptr; | |
150 | + } | |
151 | + m_rtpSessionPtr->Destroy(); | |
152 | + | |
153 | + ClosePsThread(); | |
154 | + | |
155 | + m_bOpened = false; | |
156 | + | |
157 | + LOG_INFO("[{}] closed.", m_deviceID); | |
158 | +} | |
159 | + | |
160 | +// 收RTP包线程 | |
161 | +int RTPUdpReceiver::OnRtpRecv() | |
162 | +{ | |
163 | + if(nullptr == m_rtpSessionPtr){ | |
164 | + return -1; | |
165 | + } | |
166 | + | |
167 | + LOG_INFO("[{}] OnRtpRecv started.", m_deviceID); | |
168 | + while (!m_bRtpExit) | |
169 | + { | |
170 | + //try | |
171 | + //{ | |
172 | + m_rtpSessionPtr->Poll(); | |
173 | + m_rtpSessionPtr->BeginDataAccess(); | |
174 | + | |
175 | + if (m_rtpSessionPtr->GotoFirstSourceWithData()) | |
176 | + { | |
177 | + LOG_INFO("OnRtpRecv GotoFirstSourceWithData --{}", m_deviceID); | |
178 | + last_recv_ts = get_cur_time(); | |
179 | + m_idleCount = 0; | |
180 | + m_noDataCount = 0; | |
181 | + do | |
182 | + { | |
183 | + RTPPacket* packet; | |
184 | + while ((packet = m_rtpSessionPtr->GetNextPacket()) != NULL) | |
185 | + { | |
186 | + LOG_INFO("OnRtpRecv GetNextPacket --{}", m_deviceID); | |
187 | + int ret = ParsePacket(packet); | |
188 | + m_rtpSessionPtr->DeletePacket(packet); | |
189 | + | |
190 | + if(ret != 0){ | |
191 | + m_bRtpExit = true; | |
192 | + } | |
193 | + } | |
194 | + } while (m_rtpSessionPtr->GotoNextSourceWithData()); | |
195 | + } | |
196 | + //else { | |
197 | + // if (m_idleCount != -1) | |
198 | + // { | |
199 | + // ++m_idleCount;//流中断计数 | |
200 | + // } | |
201 | + // if (m_noDataCount != 0) | |
202 | + // { | |
203 | + // --m_noDataCount;//没流计数 | |
204 | + // } | |
205 | + // //if (m_idleCount > 3000) { | |
206 | + // // m_hVodEndFunc(m_usrParam); | |
207 | + // // m_idleCount = 0; | |
208 | + // //历史流结束的时候,也会出现超时,这个是正常的 | |
209 | + // if(m_usrParam && ((VideoSession *)GetUsrParam())->video_type() == VideoType::ERECORD) | |
210 | + // { | |
211 | + // if (m_idleCount > 10000) | |
212 | + // { | |
213 | + // //这里要判断下历史流是否结束,如果未结束,就设置为流中断 | |
214 | + // //由于record_stream_status这个函数返回值不准确,所以增加一个进度条大于80% | |
215 | + // if(record_stream_status(((VideoSession *)GetUsrParam())->streamHandle())) | |
216 | + // { | |
217 | + // LOG_INFO("************Record stream is finished**{}**m_progress = {}********", m_deviceID, ((VideoSession *)GetUsrParam())->progress()); | |
218 | + // m_idleCount = -1; | |
219 | + // m_hVodEndFunc(m_usrParam); | |
220 | + // record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle()); | |
221 | + // ((VideoSession *)GetUsrParam())->streamHandle().clear(); | |
222 | + // } | |
223 | + // else | |
224 | + // { | |
225 | + // //如果此时进度大于80% 算完成吧 | |
226 | + // if(((VideoSession *)GetUsrParam())->progress() > 0.80) | |
227 | + // { | |
228 | + // LOG_INFO("************Record stream is overtime**{}**m_progress = {}********", m_deviceID, ((VideoSession *)GetUsrParam())->progress()); | |
229 | + | |
230 | + // m_idleCount = 0; | |
231 | + // m_hVodEndFunc(m_usrParam); | |
232 | + // record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle()); | |
233 | + // ((VideoSession *)GetUsrParam())->streamHandle().clear(); | |
234 | + // } | |
235 | + // else | |
236 | + // { | |
237 | + // m_idleCount = -1; | |
238 | + // //LOG_ERROR("************post ERROR_REALSTREAM_INTERRUPT to structure****{}********", m_deviceID); | |
239 | + // //发送流中断 | |
240 | + // //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Record time video streaming interruption!"); | |
241 | + // } | |
242 | + // } | |
243 | + // | |
244 | + // | |
245 | + // } | |
246 | + // | |
247 | + // if (m_noDataCount < -200000)//任务开始时没收到流 | |
248 | + // { | |
249 | + // //LOG_ERROR("************m_hVodEndFunc(m_usrParam)!!!m_hVodEndFunc(m_usrParam)********{}******", m_deviceID); | |
250 | + // m_noDataCount = -1; | |
251 | + | |
252 | + // //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Record time video streaming interruption2!"); | |
253 | + // //m_hVodEndFunc(m_usrParam); | |
254 | + // } | |
255 | + // } | |
256 | + // else//实时任务断流 | |
257 | + // //if (m_usrParam && ((VideoSession *)GetUsrParam())->video_type() == VideoType::EREAL) | |
258 | + // { | |
259 | + // | |
260 | + // //每超过3000次,发送一次send_vedio_eof 时长大约1.5s | |
261 | + // //若是30000,时长大约 18s | |
262 | + // if(m_idleCount > 30000) | |
263 | + // { | |
264 | + // uint64_t cts = get_cur_time(); | |
265 | + // float duration_not_recv = (cts - last_recv_ts) / 1000.0; | |
266 | + // | |
267 | + // //LOG_ERROR("************I haven't got stream from hik gateway exceed {}s,send eof********{}******", duration_not_recv, m_deviceID); | |
268 | + // m_idleCount = -1; | |
269 | + | |
270 | + // //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption!"); | |
271 | + // } | |
272 | + // | |
273 | + // if (m_noDataCount < -200000)//任务开始时没收到流 | |
274 | + // { | |
275 | + // //LOG_ERROR("************m_noDataCount < -200000********{}******", m_deviceID); | |
276 | + // m_noDataCount = -1; | |
277 | + | |
278 | + // //throw GeneralException2(ERROR_REALSTREAM_INTERRUPT, "Real time video streaming interruption2!"); | |
279 | + // } | |
280 | + // | |
281 | + // } | |
282 | + //} | |
283 | + //} | |
284 | + // catch (GeneralException2& e) | |
285 | + //{ | |
286 | + // //LOG_ERROR("---> video streaming interruption!<---{}, error: {}", m_deviceID, e.err_msg()); | |
287 | + | |
288 | + // byte_buffer bb(64); | |
289 | + // bb << VasCmd::VAS_CMD_REALSTREAM_INTERRUPT << e.err_msg(); | |
290 | + | |
291 | + // if (m_usrParam) | |
292 | + // { | |
293 | + // if (((VideoSession *)GetUsrParam())->msgChan()->is_valid()) { | |
294 | + // try { | |
295 | + // ((VideoSession *)GetUsrParam())->msgChan()->send_msg(bb.data_ptr(), bb.data_size()); | |
296 | + // } | |
297 | + // catch (GeneralException2& e) { | |
298 | + // //LOG_ERROR("[{}] send vas cmd VAS_CMD_REALSTREAM_INTERRUPT error: {}, {}", m_deviceID, e.err_code(), e.err_str()); | |
299 | + // } | |
300 | + // } | |
301 | + | |
302 | + // //通知网关关闭句柄 | |
303 | + // if(!((VideoSession *)GetUsrParam())->streamHandle().empty()) | |
304 | + // { | |
305 | + | |
306 | + // LOG_INFO("---->Notify hisense gateway release handle = {} !<----{}", ((VideoSession *)GetUsrParam())->streamHandle().c_str(), m_deviceID); | |
307 | + // if (((VideoSession *)GetUsrParam())->video_type() == VideoType::EREAL) | |
308 | + // real_stream_stop(((VideoSession *)GetUsrParam())->streamHandle()); | |
309 | + // | |
310 | + // if (((VideoSession *)GetUsrParam())->video_type() == VideoType::ERECORD) | |
311 | + // record_stream_stop(((VideoSession *)GetUsrParam())->streamHandle()); | |
312 | + // | |
313 | + // //清理保活的句柄 | |
314 | + // ((VideoSession *)GetUsrParam())->streamHandle().clear(); | |
315 | + // } | |
316 | + // } | |
317 | + // | |
318 | + // bb.bset(0); | |
319 | + // | |
320 | + //} | |
321 | + m_rtpSessionPtr->EndDataAccess(); | |
322 | + | |
323 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
324 | + } | |
325 | + | |
326 | + LOG_INFO("[{}] OnRtpRecv exited.", m_deviceID); | |
327 | + | |
328 | + return 0; | |
329 | +} | |
330 | + | |
331 | + | ... | ... |
src/gb28181/RTPUdpReceiver.h
0 → 100644
1 | +#ifndef _RTP_UDP_RECEIVER_H_ | |
2 | +#define _RTP_UDP_RECEIVER_H_ | |
3 | + | |
4 | +#include "rtpudpv4transmitter.h" | |
5 | +#include "rtpipv4address.h" | |
6 | +#include "rtpsessionparams.h" | |
7 | +#include "rtpsession.h" | |
8 | +#include <queue> | |
9 | +#include <iostream> | |
10 | +#include <thread> | |
11 | +#include <string> | |
12 | +#include <mutex> | |
13 | + | |
14 | +#include "RTPReceiver.h" | |
15 | + | |
16 | + | |
17 | +#define OUTTIME_RTCP 30*1000 | |
18 | +#define PAYLOAD 99 | |
19 | +#define PAYLOAD_PS 96 | |
20 | +#define PAYLOAD_H264 98 | |
21 | +#define PAYLOAD_MP4 97 | |
22 | + | |
23 | +#define UDP_SIZE 1400 | |
24 | +#define MIN_PORT 10000 | |
25 | +#define MAX_PORT 60000 | |
26 | +#define RTP_MAX_PACKET_LEN 1450 | |
27 | + | |
28 | +using namespace jrtplib; | |
29 | +using namespace std; | |
30 | + | |
31 | + | |
32 | +class UdpRTPSession; | |
33 | + | |
34 | +class RTPUdpReceiver: public RTPReceiver | |
35 | +{ | |
36 | +public: | |
37 | + RTPUdpReceiver(); | |
38 | + ~RTPUdpReceiver(); | |
39 | + | |
40 | + virtual bool Open(uint16_t localPort); | |
41 | + virtual bool IsOpened() ; | |
42 | + virtual void Close() ; | |
43 | + | |
44 | +public: | |
45 | + int OnRtpRecv(); | |
46 | + | |
47 | +private: | |
48 | + std::thread* m_rtpThreadPtr; // RTP接收线程 | |
49 | + | |
50 | + UdpRTPSession* m_rtpSessionPtr; // RTP会话 | |
51 | + std::atomic_bool m_bRtpExit; // 标识RTP收包线程闭 | |
52 | + | |
53 | + std::atomic_bool m_bOpened; | |
54 | + | |
55 | + int64_t m_idleCount; | |
56 | + int64_t m_noDataCount;//线程计数,用于打开流成功但是实际没流过来 | |
57 | + | |
58 | + RTPSessionParams* m_sessparamsPtr; | |
59 | + RTPUDPv4TransmissionParams* m_transparamsPtr; | |
60 | +}; | |
61 | + | |
62 | +#endif // _RTP_UDP_RECEIVER_H_ | ... | ... |
src/gb28181/demuxer.h
... | ... | @@ -8,6 +8,9 @@ |
8 | 8 | { CMpeg2Demux class. } |
9 | 9 | { } |
10 | 10 | {*******************************************************/ |
11 | +#ifndef _DEMUXER_H_ | |
12 | +#define _DEMUXER_H_ | |
13 | + | |
11 | 14 | #include <stdint.h> |
12 | 15 | #include "buffer.h" |
13 | 16 | |
... | ... | @@ -46,8 +49,8 @@ |
46 | 49 | //typedef long long INT64; |
47 | 50 | //typedef unsigned long long UINT64; |
48 | 51 | |
49 | -typedef int ReceiveFunction(unsigned char streamType, void* data, int size, uint64_t pts, uint64_t localPts, bool bKey, void* userData);//es»Øµ÷ | |
50 | -typedef int ReceiveFunction2(unsigned int streamtype, void * Data, int Size, uint64_t pts, bool iskeyfram, void* userdata);//ps»Øµ÷ | |
52 | +typedef int ReceiveFunction(unsigned char streamType, void* data, int size, uint64_t pts, uint64_t localPts, bool bKey, void* userData);//es�ص� | |
53 | +typedef int ReceiveFunction2(unsigned int streamtype, void * Data, int Size, uint64_t pts, bool iskeyfram, void* userdata);//ps�ص� | |
51 | 54 | |
52 | 55 | static /*_inline*/ unsigned int asm_swap32(unsigned int x); |
53 | 56 | static /*_inline*/ unsigned short asm_swap16(unsigned short x); |
... | ... | @@ -77,4 +80,6 @@ public: |
77 | 80 | int AddData(void * Data, int Size/*, DWORD pts*/); |
78 | 81 | void SetReceiveFunction(ReceiveFunction * func, void* userdata); |
79 | 82 | void SetReceiveFunction2(ReceiveFunction2 * func2, void* userdata2); |
80 | -}; | |
81 | 83 | \ No newline at end of file |
84 | +}; | |
85 | + | |
86 | +#endif // _DEMUXER_H_ | |
82 | 87 | \ No newline at end of file | ... | ... |
src/main.cpp
... | ... | @@ -28,8 +28,6 @@ |
28 | 28 | #define MIN_RTP_PORT 10000 |
29 | 29 | #define MAX_RTP_PORT 60000 |
30 | 30 | |
31 | -string data_home = "/mnt/f/fiss/data/"; | |
32 | - | |
33 | 31 | // ȡ MIN_RTP_PORT(10000)~MAX_RTP_PORT(60000)֮�������˿�(ż���������������˿ڿ���) |
34 | 32 | int allocRtpPort() { |
35 | 33 | |
... | ... | @@ -90,7 +88,7 @@ int sum2 = 0; |
90 | 88 | |
91 | 89 | cudaStream_t stream[2]; |
92 | 90 | |
93 | -string data_home = "/mnt/data/cmhu/FFNvDecoder/data/"; | |
91 | +string data_home = "/data/tongtu/"; | |
94 | 92 | |
95 | 93 | |
96 | 94 | #define checkCudaErrors(S) do {CUresult status; \ |
... | ... | @@ -173,7 +171,7 @@ void postDecoded(const void * userPtr, AVFrame * gpuFrame){ |
173 | 171 | // cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl; |
174 | 172 | |
175 | 173 | int sum = sum1; |
176 | - if (decoder->getName() == "dec1") | |
174 | + if (decoder->getName() == "dec0") | |
177 | 175 | { |
178 | 176 | sum1 ++ ; |
179 | 177 | sum = sum1; |
... | ... | @@ -301,17 +299,17 @@ void decode_finished_cbk(const void* userPtr){ |
301 | 299 | cout << "当前时间戳: " << get_cur_time() << endl; |
302 | 300 | } |
303 | 301 | |
302 | +bool decode_request_stream_cbk(){ | |
303 | + cout << "需在此请求流" << endl; | |
304 | + return true; | |
305 | +} | |
306 | + | |
304 | 307 | // string test_uri = "rtmp://192.168.10.56:1935/objecteye/1"; |
305 | 308 | // string test_uri = "/home/cmhu/data/output_800x480.mp4"; |
306 | 309 | // string test_uri = "/home/cmhu/data/output_1920x1080.mp4"; |
307 | 310 | // string test_uri = "rtsp://176.10.0.2:8554/stream"; |
308 | 311 | // string test_uri = "/mnt/f/fiss/test_data/h265.mp4"; |
309 | 312 | string test_uri = "rtsp://176.10.0.4:8554/stream"; |
310 | -char* gpuid = "0"; | |
311 | -string test_uri = "ws://127.0.0.1:10000/sms/34020000002020000001/flv/hls/34020000001110005555_34020000001310005554.flv"; | |
312 | -// string test_uri = "rtsp://176.10.0.4:8554/stream"; | |
313 | - | |
314 | -char* gpu_id = "0"; | |
315 | 313 | |
316 | 314 | void createDecode(int index, const char* gpu_id){ |
317 | 315 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
... | ... | @@ -323,7 +321,7 @@ void createDecode(int index, const char* gpu_id){ |
323 | 321 | config.cfg.force_tcp = true; |
324 | 322 | config.dec_type = DECODER_TYPE_FFMPEG; |
325 | 323 | |
326 | - config.cfg.gpuid = gpuid; | |
324 | + config.cfg.gpuid = gpu_id; | |
327 | 325 | // if (index % 2 == 0) |
328 | 326 | // { |
329 | 327 | // config.cfg.gpuid = "0"; |
... | ... | @@ -343,19 +341,20 @@ void createDecode(int index, const char* gpu_id){ |
343 | 341 | pDecManager->startDecodeByName(config.name); |
344 | 342 | } |
345 | 343 | |
346 | -void createGB28181Decode(int index, char* gpuid){ | |
344 | +void createGB28181Decode(int index, char* gpu_id, int port){ | |
347 | 345 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
348 | 346 | MgrDecConfig config; |
349 | 347 | config.name = "dec" + to_string(index); |
350 | 348 | config.cfg.uri = config.name; |
351 | 349 | config.cfg.post_decoded_cbk = postDecoded; |
352 | 350 | config.cfg.decode_finished_cbk = decode_finished_cbk; |
351 | + config.cfg.request_stream_cbk = decode_request_stream_cbk; | |
353 | 352 | config.cfg.force_tcp = true; |
354 | 353 | |
355 | 354 | config.dec_type = DECODER_TYPE_GB28181; |
356 | - config.cfg.port = 30012;//allocRtpPort(); | |
355 | + config.cfg.port = port;//allocRtpPort(); | |
357 | 356 | |
358 | - config.cfg.gpuid = gpuid; | |
357 | + config.cfg.gpuid = gpu_id; | |
359 | 358 | |
360 | 359 | AbstractDecoder* decoder = pDecManager->createDecoder(config); |
361 | 360 | if (!decoder) |
... | ... | @@ -376,23 +375,14 @@ void logFF(void *, int level, const char *fmt, va_list ap) |
376 | 375 | int main(int argc, char* argv[]){ |
377 | 376 | |
378 | 377 | test_uri = argv[1]; |
379 | - gpuid = argv[2]; | |
380 | - cout << test_uri << " gpu_id:" << gpu_id << endl; | |
378 | + char* gpuid = argv[2]; | |
379 | + int port = atoi(argv[3]); | |
380 | + cout << test_uri << " gpu_id:" << gpuid << " port:" << port << endl; | |
381 | 381 | |
382 | 382 | // av_log_set_callback(&logFF); |
383 | 383 | |
384 | 384 | CheckCUDAProperty(atoi(gpuid)); |
385 | 385 | |
386 | - FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); | |
387 | - | |
388 | - // int count = 99; | |
389 | - // for (size_t i = 0; i < count ; i++) | |
390 | - // { | |
391 | - // createDecode(i); | |
392 | - // } | |
393 | - | |
394 | - | |
395 | - | |
396 | 386 | pthread_t m_decode_thread; |
397 | 387 | pthread_create(&m_decode_thread,0, |
398 | 388 | [](void* arg) |
... | ... | @@ -400,7 +390,7 @@ int main(int argc, char* argv[]){ |
400 | 390 | // cudaSetDevice(atoi(gpuid)); |
401 | 391 | while (true) |
402 | 392 | { |
403 | - std::this_thread::sleep_for(std::chrono::milliseconds(5000)); | |
393 | + std::this_thread::sleep_for(std::chrono::minutes(1)); | |
404 | 394 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
405 | 395 | int count = pDecManager->count(); |
406 | 396 | cout << "当前时间:" << get_cur_time() << " 当前运行路数: " << pDecManager->count() << endl; |
... | ... | @@ -410,8 +400,6 @@ int main(int argc, char* argv[]){ |
410 | 400 | } |
411 | 401 | ,nullptr); |
412 | 402 | |
413 | - | |
414 | - | |
415 | 403 | |
416 | 404 | FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); |
417 | 405 | int i = 0; |
... | ... | @@ -423,18 +411,17 @@ int main(int argc, char* argv[]){ |
423 | 411 | { |
424 | 412 | break; |
425 | 413 | } |
426 | - | |
427 | 414 | |
428 | 415 | switch (ch) |
429 | 416 | { |
430 | 417 | case 'f': |
431 | 418 | case 'F': |
432 | - createDecode(i, gpu_id); | |
419 | + createDecode(i, gpuid); | |
433 | 420 | i++; |
434 | 421 | break; |
435 | 422 | case 'g': |
436 | 423 | case 'G': |
437 | - createGB28181Decode(i, gpu_id); | |
424 | + createGB28181Decode(i, gpuid, port); | |
438 | 425 | i++; |
439 | 426 | break; |
440 | 427 | case 'r': | ... | ... |