| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h" | |
| 12 | |
| 13 #include <stdio.h> | |
| 14 #include <stdlib.h> | |
| 15 | |
| 16 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" | |
| 17 #include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h" | |
| 18 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | |
| 19 #include "webrtc/system_wrappers/include/event_wrapper.h" | |
| 20 #include "webrtc/system_wrappers/include/tick_util.h" | |
| 21 #include "webrtc/test/channel_transport/udp_transport.h" | |
| 22 | |
| 23 #define NR_OF_SOCKET_BUFFERS 500 | |
| 24 | |
| 25 | |
| 26 bool ProcThreadFunction(void *obj) | |
| 27 { | |
| 28 if (obj == NULL) | |
| 29 { | |
| 30 return false; | |
| 31 } | |
| 32 TestSenderReceiver *theObj = static_cast<TestSenderReceiver *>(obj); | |
| 33 | |
| 34 return theObj->ProcLoop(); | |
| 35 } | |
| 36 | |
| 37 | |
| 38 TestSenderReceiver::TestSenderReceiver (void) | |
| 39 : | |
| 40 _critSect(CriticalSectionWrapper::CreateCriticalSection()), | |
| 41 _eventPtr(NULL), | |
| 42 _procThread(ProcThreadFunction, this, "TestSenderReceiver"), | |
| 43 _running(false), | |
| 44 _payloadType(0), | |
| 45 _loadGenerator(NULL), | |
| 46 _isSender(false), | |
| 47 _isReceiver(false), | |
| 48 _sendRecCB(NULL), | |
| 49 _lastBytesReceived(0), | |
| 50 _lastTime(-1) | |
| 51 { | |
| 52 // RTP/RTCP module | |
| 53 _rtp = RtpRtcp::CreateRtpRtcp(0, false); | |
| 54 if (!_rtp) | |
| 55 { | |
| 56 throw "Could not create RTP/RTCP module"; | |
| 57 exit(1); | |
| 58 } | |
| 59 | |
| 60 if (_rtp->InitReceiver() != 0) | |
| 61 { | |
| 62 throw "_rtp->InitReceiver()"; | |
| 63 exit(1); | |
| 64 } | |
| 65 | |
| 66 if (_rtp->InitSender() != 0) | |
| 67 { | |
| 68 throw "_rtp->InitSender()"; | |
| 69 exit(1); | |
| 70 } | |
| 71 | |
| 72 // SocketTransport module | |
| 73 uint8_t numberOfThreads = 1; | |
| 74 _transport = UdpTransport::Create(0, numberOfThreads); | |
| 75 if (!_transport) | |
| 76 { | |
| 77 throw "Could not create transport module"; | |
| 78 exit(1); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 TestSenderReceiver::~TestSenderReceiver (void) | |
| 83 { | |
| 84 | |
| 85 Stop(); // N.B. without critSect | |
| 86 | |
| 87 _critSect->Enter(); | |
| 88 | |
| 89 if (_rtp) | |
| 90 { | |
| 91 RtpRtcp::DestroyRtpRtcp(_rtp); | |
| 92 _rtp = NULL; | |
| 93 } | |
| 94 | |
| 95 if (_transport) | |
| 96 { | |
| 97 UdpTransport::Destroy(_transport); | |
| 98 _transport = NULL; | |
| 99 } | |
| 100 | |
| 101 delete _critSect; | |
| 102 | |
| 103 } | |
| 104 | |
| 105 | |
| 106 int32_t TestSenderReceiver::InitReceiver (const uint16_t rtpPort, | |
| 107 const uint16_t rtcpPort, | |
| 108 const int8_t payloadType /*= 127*/) | |
| 109 { | |
| 110 CriticalSectionScoped cs(_critSect); | |
| 111 | |
| 112 // init transport | |
| 113 if (_transport->InitializeReceiveSockets(this, rtpPort/*, 0, NULL, 0, true*/
) != 0) | |
| 114 { | |
| 115 throw "_transport->InitializeReceiveSockets"; | |
| 116 exit(1); | |
| 117 } | |
| 118 | |
| 119 if (_rtp->RegisterIncomingRTPCallback(this) != 0) | |
| 120 { | |
| 121 throw "_rtp->RegisterIncomingRTPCallback"; | |
| 122 exit(1); | |
| 123 } | |
| 124 | |
| 125 if (_rtp->RegisterIncomingDataCallback(this) != 0) | |
| 126 { | |
| 127 throw "_rtp->RegisterIncomingRTPCallback"; | |
| 128 exit(1); | |
| 129 } | |
| 130 | |
| 131 if (_rtp->SetRTCPStatus(RtcpMode::kReducedSize) != 0) { | |
| 132 throw "_rtp->SetRTCPStatus"; | |
| 133 exit(1); | |
| 134 } | |
| 135 | |
| 136 if (_rtp->SetTMMBRStatus(true) != 0) | |
| 137 { | |
| 138 throw "_rtp->SetTMMBRStatus"; | |
| 139 exit(1); | |
| 140 } | |
| 141 | |
| 142 if (_rtp->RegisterReceivePayload("I420", payloadType, 90000) != 0) | |
| 143 { | |
| 144 throw "_rtp->RegisterReceivePayload"; | |
| 145 exit(1); | |
| 146 } | |
| 147 | |
| 148 _isReceiver = true; | |
| 149 | |
| 150 return (0); | |
| 151 } | |
| 152 | |
| 153 | |
| 154 int32_t TestSenderReceiver::Start() | |
| 155 { | |
| 156 CriticalSectionScoped cs(_critSect); | |
| 157 | |
| 158 _eventPtr = EventWrapper::Create(); | |
| 159 | |
| 160 if (_rtp->SetSendingStatus(true) != 0) | |
| 161 { | |
| 162 throw "_rtp->SetSendingStatus"; | |
| 163 exit(1); | |
| 164 } | |
| 165 | |
| 166 _running = true; | |
| 167 | |
| 168 if (_isReceiver) | |
| 169 { | |
| 170 if (_transport->StartReceiving(NR_OF_SOCKET_BUFFERS) != 0) | |
| 171 { | |
| 172 throw "_transport->StartReceiving"; | |
| 173 exit(1); | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 _procThread.Start(); | |
| 178 _procThread.SetPriority(rtc::kRealtimePriority); | |
| 179 | |
| 180 return 0; | |
| 181 | |
| 182 } | |
| 183 | |
| 184 | |
| 185 int32_t TestSenderReceiver::Stop () | |
| 186 { | |
| 187 CriticalSectionScoped cs(_critSect); | |
| 188 | |
| 189 _transport->StopReceiving(); | |
| 190 | |
| 191 if (_running) | |
| 192 { | |
| 193 _running = false; | |
| 194 _eventPtr->Set(); | |
| 195 | |
| 196 _procThread.Stop(); | |
| 197 | |
| 198 delete _eventPtr; | |
| 199 } | |
| 200 | |
| 201 return (0); | |
| 202 } | |
| 203 | |
| 204 | |
| 205 bool TestSenderReceiver::ProcLoop(void) | |
| 206 { | |
| 207 | |
| 208 // process RTP/RTCP module | |
| 209 _rtp->Process(); | |
| 210 | |
| 211 // process SocketTransport module | |
| 212 _transport->Process(); | |
| 213 | |
| 214 // no critSect | |
| 215 while (_running) | |
| 216 { | |
| 217 // ask RTP/RTCP module for wait time | |
| 218 int32_t rtpWait = _rtp->TimeUntilNextProcess(); | |
| 219 | |
| 220 // ask SocketTransport module for wait time | |
| 221 int32_t tpWait = _transport->TimeUntilNextProcess(); | |
| 222 | |
| 223 int32_t minWait = (rtpWait < tpWait) ? rtpWait: tpWait; | |
| 224 minWait = (minWait > 0) ? minWait : 0; | |
| 225 // wait | |
| 226 _eventPtr->Wait(minWait); | |
| 227 | |
| 228 // process RTP/RTCP module | |
| 229 _rtp->Process(); | |
| 230 | |
| 231 // process SocketTransport module | |
| 232 _transport->Process(); | |
| 233 | |
| 234 } | |
| 235 | |
| 236 return true; | |
| 237 } | |
| 238 | |
| 239 | |
| 240 int32_t TestSenderReceiver::ReceiveBitrateKbps () | |
| 241 { | |
| 242 size_t bytesSent; | |
| 243 uint32_t packetsSent; | |
| 244 size_t bytesReceived; | |
| 245 uint32_t packetsReceived; | |
| 246 | |
| 247 if (_rtp->DataCountersRTP(&bytesSent, &packetsSent, &bytesReceived, &packets
Received) == 0) | |
| 248 { | |
| 249 int64_t now = TickTime::MillisecondTimestamp(); | |
| 250 int32_t kbps = 0; | |
| 251 if (now > _lastTime) | |
| 252 { | |
| 253 if (_lastTime > 0) | |
| 254 { | |
| 255 // 8 * bytes / ms = kbps | |
| 256 kbps = static_cast<int32_t>( | |
| 257 (8 * (bytesReceived - _lastBytesReceived)) / (now - _lastTim
e)); | |
| 258 } | |
| 259 _lastTime = now; | |
| 260 _lastBytesReceived = bytesReceived; | |
| 261 } | |
| 262 return (kbps); | |
| 263 } | |
| 264 | |
| 265 return (-1); | |
| 266 } | |
| 267 | |
| 268 | |
| 269 int32_t TestSenderReceiver::SetPacketTimeout(const uint32_t timeoutMS) | |
| 270 { | |
| 271 return (_rtp->SetPacketTimeout(timeoutMS, 0 /* RTCP timeout */)); | |
| 272 } | |
| 273 | |
| 274 | |
| 275 int32_t TestSenderReceiver::OnReceivedPayloadData(const uint8_t* payloadData, | |
| 276 const size_t payloadSize, | |
| 277 const webrtc::WebRtcRTPHeader*
rtpHeader) | |
| 278 { | |
| 279 //printf("OnReceivedPayloadData\n"); | |
| 280 return (0); | |
| 281 } | |
| 282 | |
| 283 | |
| 284 void TestSenderReceiver::IncomingRTPPacket(const int8_t* incomingRtpPacket, | |
| 285 const size_t rtpPacketLength, | |
| 286 const int8_t* fromIP, | |
| 287 const uint16_t fromPort) | |
| 288 { | |
| 289 _rtp->IncomingPacket((uint8_t *) incomingRtpPacket, rtpPacketLength); | |
| 290 } | |
| 291 | |
| 292 | |
| 293 | |
| 294 void TestSenderReceiver::IncomingRTCPPacket(const int8_t* incomingRtcpPacket, | |
| 295 const size_t rtcpPacketLength, | |
| 296 const int8_t* fromIP, | |
| 297 const uint16_t fromPort) | |
| 298 { | |
| 299 _rtp->IncomingPacket((uint8_t *) incomingRtcpPacket, rtcpPacketLength); | |
| 300 } | |
| 301 | |
| 302 | |
| 303 | |
| 304 | |
| 305 | |
| 306 /////////////////// | |
| 307 | |
| 308 | |
| 309 int32_t TestSenderReceiver::InitSender (const uint32_t startBitrateKbps, | |
| 310 const int8_t* ipAddr, | |
| 311 const uint16_t rtpPort, | |
| 312 const uint16_t rtcpPort /*= 0*/, | |
| 313 const int8_t payloadType /*= 127*/) | |
| 314 { | |
| 315 CriticalSectionScoped cs(_critSect); | |
| 316 | |
| 317 _payloadType = payloadType; | |
| 318 | |
| 319 // check load generator valid | |
| 320 if (_loadGenerator) | |
| 321 { | |
| 322 _loadGenerator->SetBitrate(startBitrateKbps); | |
| 323 } | |
| 324 | |
| 325 if (_rtp->RegisterSendTransport(_transport) != 0) | |
| 326 { | |
| 327 throw "_rtp->RegisterSendTransport"; | |
| 328 exit(1); | |
| 329 } | |
| 330 if (_rtp->RegisterSendPayload("I420", _payloadType, 90000) != 0) | |
| 331 { | |
| 332 throw "_rtp->RegisterSendPayload"; | |
| 333 exit(1); | |
| 334 } | |
| 335 | |
| 336 if (_rtp->RegisterIncomingVideoCallback(this) != 0) | |
| 337 { | |
| 338 throw "_rtp->RegisterIncomingVideoCallback"; | |
| 339 exit(1); | |
| 340 } | |
| 341 | |
| 342 if (_rtp->SetRTCPStatus(RtcpMode::kReducedSize) != 0) { | |
| 343 throw "_rtp->SetRTCPStatus"; | |
| 344 exit(1); | |
| 345 } | |
| 346 | |
| 347 if (_rtp->SetSendBitrate(startBitrateKbps*1000, 0, MAX_BITRATE_KBPS) != 0) | |
| 348 { | |
| 349 throw "_rtp->SetSendBitrate"; | |
| 350 exit(1); | |
| 351 } | |
| 352 | |
| 353 | |
| 354 // SocketTransport | |
| 355 if (_transport->InitializeSendSockets(ipAddr, rtpPort, rtcpPort)) | |
| 356 { | |
| 357 throw "_transport->InitializeSendSockets"; | |
| 358 exit(1); | |
| 359 } | |
| 360 | |
| 361 _isSender = true; | |
| 362 | |
| 363 return (0); | |
| 364 } | |
| 365 | |
| 366 | |
| 367 | |
| 368 int32_t | |
| 369 TestSenderReceiver::SendOutgoingData(const uint32_t timeStamp, | |
| 370 const uint8_t* payloadData, | |
| 371 const size_t payloadSize, | |
| 372 const webrtc::FrameType frameType /*= webrt
c::kVideoFrameDelta*/) | |
| 373 { | |
| 374 return (_rtp->SendOutgoingData(frameType, _payloadType, timeStamp, payloadDa
ta, payloadSize)); | |
| 375 } | |
| 376 | |
| 377 | |
| 378 int32_t TestSenderReceiver::SetLoadGenerator(TestLoadGenerator *generator) | |
| 379 { | |
| 380 CriticalSectionScoped cs(_critSect); | |
| 381 | |
| 382 _loadGenerator = generator; | |
| 383 return(0); | |
| 384 | |
| 385 } | |
| 386 | |
| 387 void TestSenderReceiver::OnNetworkChanged(const int32_t id, | |
| 388 const uint32_t minBitrateBps, | |
| 389 const uint32_t maxBitrateBps, | |
| 390 const uint8_t fractionLost, | |
| 391 const uint16_t roundTripTimeMs, | |
| 392 const uint16_t bwEstimateKbitMin, | |
| 393 const uint16_t bwEstimateKbitMax) | |
| 394 { | |
| 395 if (_loadGenerator) | |
| 396 { | |
| 397 _loadGenerator->SetBitrate(maxBitrateBps/1000); | |
| 398 } | |
| 399 | |
| 400 if (_sendRecCB) | |
| 401 { | |
| 402 _sendRecCB->OnOnNetworkChanged(maxBitrateBps, | |
| 403 fractionLost, | |
| 404 roundTripTimeMs, | |
| 405 bwEstimateKbitMin, | |
| 406 bwEstimateKbitMax); | |
| 407 } | |
| 408 } | |
| OLD | NEW |