1 /* 2 * Copyright (c) 2012 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/video_coding/main/test/test_callbacks.h" 12 13 #include <math.h> 14 15 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 16 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" 17 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" 18 #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" 19 #include "webrtc/modules/utility/interface/rtp_dump.h" 20 #include "webrtc/modules/video_coding/main/test/test_macros.h" 21 #include "webrtc/system_wrappers/interface/clock.h" 22 23 namespace webrtc { 24 25 /****************************** 26 * VCMEncodeCompleteCallback 27 *****************************/ 28 // Basic callback implementation 29 // passes the encoded frame directly to the encoder 30 // Packetization callback implementation 31 VCMEncodeCompleteCallback::VCMEncodeCompleteCallback(FILE* encodedFile): 32 _encodedFile(encodedFile), 33 _encodedBytes(0), 34 _VCMReceiver(NULL), 35 _seqNo(0), 36 _encodeComplete(false), 37 _width(0), 38 _height(0), 39 _codecType(kRtpVideoNone) 40 { 41 // 42 } 43 VCMEncodeCompleteCallback::~VCMEncodeCompleteCallback() 44 { 45 } 46 47 void 48 VCMEncodeCompleteCallback::RegisterTransportCallback( 49 VCMPacketizationCallback* transport) 50 { 51 } 52 53 int32_t 54 VCMEncodeCompleteCallback::SendData( 55 const FrameType frameType, 56 const uint8_t payloadType, 57 const uint32_t timeStamp, 58 int64_t capture_time_ms, 59 const uint8_t* payloadData, 60 const uint32_t payloadSize, 61 const RTPFragmentationHeader& fragmentationHeader, 62 const RTPVideoHeader* videoHdr) 63 { 64 // will call the VCMReceiver input packet 65 _frameType = frameType; 66 // writing encodedData into file 67 if (fwrite(payloadData, 1, payloadSize, _encodedFile) != payloadSize) { 68 return -1; 69 } 70 WebRtcRTPHeader rtpInfo; 71 rtpInfo.header.markerBit = true; // end of frame 72 rtpInfo.type.Video.isFirstPacket = true; 73 rtpInfo.type.Video.codec = _codecType; 74 rtpInfo.type.Video.height = (uint16_t)_height; 75 rtpInfo.type.Video.width = (uint16_t)_width; 76 switch (_codecType) 77 { 78 case webrtc::kRtpVideoVp8: 79 rtpInfo.type.Video.codecHeader.VP8.InitRTPVideoHeaderVP8(); 80 rtpInfo.type.Video.codecHeader.VP8.nonReference = 81 videoHdr->codecHeader.VP8.nonReference; 82 rtpInfo.type.Video.codecHeader.VP8.pictureId = 83 videoHdr->codecHeader.VP8.pictureId; 84 break; 85 default: 86 assert(false); 87 return -1; 88 } 89 90 rtpInfo.header.payloadType = payloadType; 91 rtpInfo.header.sequenceNumber = _seqNo++; 92 rtpInfo.header.ssrc = 0; 93 rtpInfo.header.timestamp = timeStamp; 94 rtpInfo.frameType = frameType; 95 // Size should also be received from that table, since the payload type 96 // defines the size. 97 98 _encodedBytes += payloadSize; 99 // directly to receiver 100 int ret = _VCMReceiver->IncomingPacket(payloadData, payloadSize, rtpInfo); 101 _encodeComplete = true; 102 103 return ret; 104 } 105 106 float 107 VCMEncodeCompleteCallback::EncodedBytes() 108 { 109 return _encodedBytes; 110 } 111 112 bool 113 VCMEncodeCompleteCallback::EncodeComplete() 114 { 115 if (_encodeComplete) 116 { 117 _encodeComplete = false; 118 return true; 119 } 120 return false; 121 } 122 123 void 124 VCMEncodeCompleteCallback::Initialize() 125 { 126 _encodeComplete = false; 127 _encodedBytes = 0; 128 _seqNo = 0; 129 return; 130 } 131 132 void 133 VCMEncodeCompleteCallback::ResetByteCount() 134 { 135 _encodedBytes = 0; 136 } 137 138 /***********************************/ 139 /* VCMRTPEncodeCompleteCallback */ 140 /***********************************/ 141 // Encode Complete callback implementation 142 // passes the encoded frame via the RTP module to the decoder 143 // Packetization callback implementation 144 145 int32_t 146 VCMRTPEncodeCompleteCallback::SendData( 147 const FrameType frameType, 148 const uint8_t payloadType, 149 const uint32_t timeStamp, 150 int64_t capture_time_ms, 151 const uint8_t* payloadData, 152 const uint32_t payloadSize, 153 const RTPFragmentationHeader& fragmentationHeader, 154 const RTPVideoHeader* videoHdr) 155 { 156 _frameType = frameType; 157 _encodedBytes+= payloadSize; 158 _encodeComplete = true; 159 return _RTPModule->SendOutgoingData(frameType, 160 payloadType, 161 timeStamp, 162 capture_time_ms, 163 payloadData, 164 payloadSize, 165 &fragmentationHeader, 166 videoHdr); 167 } 168 169 float 170 VCMRTPEncodeCompleteCallback::EncodedBytes() 171 { 172 // only good for one call - after which will reset value; 173 float tmp = _encodedBytes; 174 _encodedBytes = 0; 175 return tmp; 176 } 177 178 bool 179 VCMRTPEncodeCompleteCallback::EncodeComplete() 180 { 181 if (_encodeComplete) 182 { 183 _encodeComplete = false; 184 return true; 185 } 186 return false; 187 } 188 189 // Decoded Frame Callback Implementation 190 191 int32_t 192 VCMDecodeCompleteCallback::FrameToRender(I420VideoFrame& videoFrame) 193 { 194 if (PrintI420VideoFrame(videoFrame, _decodedFile) < 0) { 195 return -1; 196 } 197 _decodedBytes+= CalcBufferSize(kI420, videoFrame.width(), 198 videoFrame.height()); 199 return VCM_OK; 200 } 201 202 int32_t 203 VCMDecodeCompleteCallback::DecodedBytes() 204 { 205 return _decodedBytes; 206 } 207 208 RTPSendCompleteCallback::RTPSendCompleteCallback(Clock* clock, 209 const char* filename): 210 _clock(clock), 211 _sendCount(0), 212 rtp_payload_registry_(NULL), 213 rtp_receiver_(NULL), 214 _rtp(NULL), 215 _lossPct(0), 216 _burstLength(0), 217 _networkDelayMs(0), 218 _jitterVar(0), 219 _prevLossState(0), 220 _totalSentLength(0), 221 _rtpPackets(), 222 _rtpDump(NULL) 223 { 224 if (filename != NULL) 225 { 226 _rtpDump = RtpDump::CreateRtpDump(); 227 _rtpDump->Start(filename); 228 } 229 } 230 231 RTPSendCompleteCallback::~RTPSendCompleteCallback() 232 { 233 if (_rtpDump != NULL) 234 { 235 _rtpDump->Stop(); 236 RtpDump::DestroyRtpDump(_rtpDump); 237 } 238 // Delete remaining packets 239 while (!_rtpPackets.empty()) 240 { 241 // Take first packet in list 242 delete _rtpPackets.front(); 243 _rtpPackets.pop_front(); 244 } 245 } 246 247 int 248 RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len) 249 { 250 _sendCount++; 251 _totalSentLength += len; 252 253 if (_rtpDump != NULL) 254 { 255 if (_rtpDump->DumpPacket((const uint8_t*)data, len) != 0) 256 { 257 return -1; 258 } 259 } 260 261 bool transmitPacket = true; 262 transmitPacket = PacketLoss(); 263 264 int64_t now = _clock->TimeInMilliseconds(); 265 // Insert outgoing packet into list 266 if (transmitPacket) 267 { 268 RtpPacket* newPacket = new RtpPacket(); 269 memcpy(newPacket->data, data, len); 270 newPacket->length = len; 271 // Simulate receive time = network delay + packet jitter 272 // simulated as a Normal distribution random variable with 273 // mean = networkDelay and variance = jitterVar 274 int32_t 275 simulatedDelay = (int32_t)NormalDist(_networkDelayMs, 276 sqrt(_jitterVar)); 277 newPacket->receiveTime = now + simulatedDelay; 278 _rtpPackets.push_back(newPacket); 279 } 280 281 // Are we ready to send packets to the receiver? 282 RtpPacket* packet = NULL; 283 284 while (!_rtpPackets.empty()) 285 { 286 // Take first packet in list 287 packet = _rtpPackets.front(); 288 int64_t timeToReceive = packet->receiveTime - now; 289 if (timeToReceive > 0) 290 { 291 // No available packets to send 292 break; 293 } 294 295 _rtpPackets.pop_front(); 296 assert(_rtp); // We must have a configured RTP module for this test. 297 // Send to receive side 298 RTPHeader header; 299 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); 300 if (!parser->Parse(packet->data, packet->length, &header)) { 301 delete packet; 302 return -1; 303 } 304 PayloadUnion payload_specific; 305 if (!rtp_payload_registry_->GetPayloadSpecifics( 306 header.payloadType, &payload_specific)) { 307 return -1; 308 } 309 if (!rtp_receiver_->IncomingRtpPacket(header, packet->data, 310 packet->length, payload_specific, 311 true)) 312 { 313 delete packet; 314 return -1; 315 } 316 delete packet; 317 packet = NULL; 318 } 319 return len; // OK 320 } 321 322 int 323 RTPSendCompleteCallback::SendRTCPPacket(int channel, const void *data, int len) 324 { 325 // Incorporate network conditions 326 return SendPacket(channel, data, len); 327 } 328 329 void 330 RTPSendCompleteCallback::SetLossPct(double lossPct) 331 { 332 _lossPct = lossPct; 333 return; 334 } 335 336 void 337 RTPSendCompleteCallback::SetBurstLength(double burstLength) 338 { 339 _burstLength = burstLength; 340 return; 341 } 342 343 bool 344 RTPSendCompleteCallback::PacketLoss() 345 { 346 bool transmitPacket = true; 347 if (_burstLength <= 1.0) 348 { 349 // Random loss: if _burstLength parameter is not set, or <=1 350 if (UnifomLoss(_lossPct)) 351 { 352 // drop 353 transmitPacket = false; 354 } 355 } 356 else 357 { 358 // Simulate bursty channel (Gilbert model) 359 // (1st order) Markov chain model with memory of the previous/last 360 // packet state (loss or received) 361 362 // 0 = received state 363 // 1 = loss state 364 365 // probTrans10: if previous packet is lost, prob. to -> received state 366 // probTrans11: if previous packet is lost, prob. to -> loss state 367 368 // probTrans01: if previous packet is received, prob. to -> loss state 369 // probTrans00: if previous packet is received, prob. to -> received 370 371 // Map the two channel parameters (average loss rate and burst length) 372 // to the transition probabilities: 373 double probTrans10 = 100 * (1.0 / _burstLength); 374 double probTrans11 = (100.0 - probTrans10); 375 double probTrans01 = (probTrans10 * ( _lossPct / (100.0 - _lossPct))); 376 377 // Note: Random loss (Bernoulli) model is a special case where: 378 // burstLength = 100.0 / (100.0 - _lossPct) (i.e., p10 + p01 = 100) 379 380 if (_prevLossState == 0 ) 381 { 382 // previous packet was received 383 if (UnifomLoss(probTrans01)) 384 { 385 // drop, update previous state to loss 386 _prevLossState = 1; 387 transmitPacket = false; 388 } 389 } 390 else if (_prevLossState == 1) 391 { 392 _prevLossState = 0; 393 // previous packet was lost 394 if (UnifomLoss(probTrans11)) 395 { 396 // drop, update previous state to loss 397 _prevLossState = 1; 398 transmitPacket = false; 399 } 400 } 401 } 402 return transmitPacket; 403 } 404 405 406 bool 407 RTPSendCompleteCallback::UnifomLoss(double lossPct) 408 { 409 double randVal = (rand() + 1.0) / (RAND_MAX + 1.0); 410 return randVal < lossPct/100; 411 } 412 413 int32_t 414 PacketRequester::ResendPackets(const uint16_t* sequenceNumbers, 415 uint16_t length) 416 { 417 return _rtp.SendNACK(sequenceNumbers, length); 418 } 419 420 int32_t 421 SendStatsTest::SendStatistics(const uint32_t bitRate, 422 const uint32_t frameRate) 423 { 424 TEST(frameRate <= _framerate); 425 TEST(bitRate > _bitrate / 2 && bitRate < 3 * _bitrate / 2); 426 printf("VCM 1 sec: Bit rate: %u\tFrame rate: %u\n", bitRate, frameRate); 427 return 0; 428 } 429 430 int32_t KeyFrameReqTest::RequestKeyFrame() { 431 printf("Key frame requested\n"); 432 return 0; 433 } 434 435 436 VideoProtectionCallback::VideoProtectionCallback(): 437 delta_fec_params_(), 438 key_fec_params_() 439 { 440 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); 441 memset(&key_fec_params_, 0, sizeof(key_fec_params_)); 442 } 443 444 VideoProtectionCallback::~VideoProtectionCallback() 445 { 446 // 447 } 448 449 int32_t 450 VideoProtectionCallback::ProtectionRequest( 451 const FecProtectionParams* delta_fec_params, 452 const FecProtectionParams* key_fec_params, 453 uint32_t* sent_video_rate_bps, 454 uint32_t* sent_nack_rate_bps, 455 uint32_t* sent_fec_rate_bps) 456 { 457 key_fec_params_ = *key_fec_params; 458 delta_fec_params_ = *delta_fec_params; 459 460 // Update RTP 461 if (_rtp->SetFecParameters(&delta_fec_params_, 462 &key_fec_params_) != 0) 463 { 464 printf("Error in Setting FEC rate\n"); 465 return -1; 466 467 } 468 return 0; 469 470 } 471 472 FecProtectionParams VideoProtectionCallback::DeltaFecParameters() const 473 { 474 return delta_fec_params_; 475 } 476 477 FecProtectionParams VideoProtectionCallback::KeyFecParameters() const 478 { 479 return key_fec_params_; 480 } 481 } // namespace webrtc 482