2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/video_coding/main/test/test_callbacks.h"
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"
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),
36 _encodeComplete(false),
39 _codecType(kRtpVideoNone)
43 VCMEncodeCompleteCallback::~VCMEncodeCompleteCallback()
48 VCMEncodeCompleteCallback::RegisterTransportCallback(
49 VCMPacketizationCallback* transport)
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)
64 // will call the VCMReceiver input packet
65 _frameType = frameType;
66 // writing encodedData into file
67 if (fwrite(payloadData, 1, payloadSize, _encodedFile) != payloadSize) {
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;
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;
85 case webrtc::kRtpVideoGeneric:
86 // Leave for now, until we add kRtpVideoVp9 to RTP.
93 rtpInfo.header.payloadType = payloadType;
94 rtpInfo.header.sequenceNumber = _seqNo++;
95 rtpInfo.header.ssrc = 0;
96 rtpInfo.header.timestamp = timeStamp;
97 rtpInfo.frameType = frameType;
98 // Size should also be received from that table, since the payload type
101 _encodedBytes += payloadSize;
102 // directly to receiver
103 int ret = _VCMReceiver->IncomingPacket(payloadData, payloadSize, rtpInfo);
104 _encodeComplete = true;
110 VCMEncodeCompleteCallback::EncodedBytes()
112 return _encodedBytes;
116 VCMEncodeCompleteCallback::EncodeComplete()
120 _encodeComplete = false;
127 VCMEncodeCompleteCallback::Initialize()
129 _encodeComplete = false;
136 VCMEncodeCompleteCallback::ResetByteCount()
141 /***********************************/
142 /* VCMRTPEncodeCompleteCallback */
143 /***********************************/
144 // Encode Complete callback implementation
145 // passes the encoded frame via the RTP module to the decoder
146 // Packetization callback implementation
149 VCMRTPEncodeCompleteCallback::SendData(
150 const FrameType frameType,
151 const uint8_t payloadType,
152 const uint32_t timeStamp,
153 int64_t capture_time_ms,
154 const uint8_t* payloadData,
155 const uint32_t payloadSize,
156 const RTPFragmentationHeader& fragmentationHeader,
157 const RTPVideoHeader* videoHdr)
159 _frameType = frameType;
160 _encodedBytes+= payloadSize;
161 _encodeComplete = true;
162 return _RTPModule->SendOutgoingData(frameType,
168 &fragmentationHeader,
173 VCMRTPEncodeCompleteCallback::EncodedBytes()
175 // only good for one call - after which will reset value;
176 float tmp = _encodedBytes;
182 VCMRTPEncodeCompleteCallback::EncodeComplete()
186 _encodeComplete = false;
192 // Decoded Frame Callback Implementation
195 VCMDecodeCompleteCallback::FrameToRender(I420VideoFrame& videoFrame)
197 if (PrintI420VideoFrame(videoFrame, _decodedFile) < 0) {
200 _decodedBytes+= CalcBufferSize(kI420, videoFrame.width(),
201 videoFrame.height());
206 VCMDecodeCompleteCallback::DecodedBytes()
208 return _decodedBytes;
211 RTPSendCompleteCallback::RTPSendCompleteCallback(Clock* clock,
212 const char* filename):
215 rtp_payload_registry_(NULL),
227 if (filename != NULL)
229 _rtpDump = RtpDump::CreateRtpDump();
230 _rtpDump->Start(filename);
234 RTPSendCompleteCallback::~RTPSendCompleteCallback()
236 if (_rtpDump != NULL)
239 RtpDump::DestroyRtpDump(_rtpDump);
241 // Delete remaining packets
242 while (!_rtpPackets.empty())
244 // Take first packet in list
245 delete _rtpPackets.front();
246 _rtpPackets.pop_front();
251 RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len)
254 _totalSentLength += len;
256 if (_rtpDump != NULL)
258 if (_rtpDump->DumpPacket((const uint8_t*)data, len) != 0)
264 bool transmitPacket = true;
265 transmitPacket = PacketLoss();
267 int64_t now = _clock->TimeInMilliseconds();
268 // Insert outgoing packet into list
271 RtpPacket* newPacket = new RtpPacket();
272 memcpy(newPacket->data, data, len);
273 newPacket->length = len;
274 // Simulate receive time = network delay + packet jitter
275 // simulated as a Normal distribution random variable with
276 // mean = networkDelay and variance = jitterVar
278 simulatedDelay = (int32_t)NormalDist(_networkDelayMs,
280 newPacket->receiveTime = now + simulatedDelay;
281 _rtpPackets.push_back(newPacket);
284 // Are we ready to send packets to the receiver?
285 RtpPacket* packet = NULL;
287 while (!_rtpPackets.empty())
289 // Take first packet in list
290 packet = _rtpPackets.front();
291 int64_t timeToReceive = packet->receiveTime - now;
292 if (timeToReceive > 0)
294 // No available packets to send
298 _rtpPackets.pop_front();
299 assert(_rtp); // We must have a configured RTP module for this test.
300 // Send to receive side
302 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
303 if (!parser->Parse(packet->data, packet->length, &header)) {
307 PayloadUnion payload_specific;
308 if (!rtp_payload_registry_->GetPayloadSpecifics(
309 header.payloadType, &payload_specific)) {
312 if (!rtp_receiver_->IncomingRtpPacket(header, packet->data,
313 packet->length, payload_specific,
326 RTPSendCompleteCallback::SendRTCPPacket(int channel, const void *data, int len)
328 // Incorporate network conditions
329 return SendPacket(channel, data, len);
333 RTPSendCompleteCallback::SetLossPct(double lossPct)
340 RTPSendCompleteCallback::SetBurstLength(double burstLength)
342 _burstLength = burstLength;
347 RTPSendCompleteCallback::PacketLoss()
349 bool transmitPacket = true;
350 if (_burstLength <= 1.0)
352 // Random loss: if _burstLength parameter is not set, or <=1
353 if (UnifomLoss(_lossPct))
356 transmitPacket = false;
361 // Simulate bursty channel (Gilbert model)
362 // (1st order) Markov chain model with memory of the previous/last
363 // packet state (loss or received)
365 // 0 = received state
368 // probTrans10: if previous packet is lost, prob. to -> received state
369 // probTrans11: if previous packet is lost, prob. to -> loss state
371 // probTrans01: if previous packet is received, prob. to -> loss state
372 // probTrans00: if previous packet is received, prob. to -> received
374 // Map the two channel parameters (average loss rate and burst length)
375 // to the transition probabilities:
376 double probTrans10 = 100 * (1.0 / _burstLength);
377 double probTrans11 = (100.0 - probTrans10);
378 double probTrans01 = (probTrans10 * ( _lossPct / (100.0 - _lossPct)));
380 // Note: Random loss (Bernoulli) model is a special case where:
381 // burstLength = 100.0 / (100.0 - _lossPct) (i.e., p10 + p01 = 100)
383 if (_prevLossState == 0 )
385 // previous packet was received
386 if (UnifomLoss(probTrans01))
388 // drop, update previous state to loss
390 transmitPacket = false;
393 else if (_prevLossState == 1)
396 // previous packet was lost
397 if (UnifomLoss(probTrans11))
399 // drop, update previous state to loss
401 transmitPacket = false;
405 return transmitPacket;
410 RTPSendCompleteCallback::UnifomLoss(double lossPct)
412 double randVal = (rand() + 1.0) / (RAND_MAX + 1.0);
413 return randVal < lossPct/100;
417 PacketRequester::ResendPackets(const uint16_t* sequenceNumbers,
420 return _rtp.SendNACK(sequenceNumbers, length);
424 SendStatsTest::SendStatistics(const uint32_t bitRate,
425 const uint32_t frameRate)
427 TEST(frameRate <= _framerate);
428 TEST(bitRate > _bitrate / 2 && bitRate < 3 * _bitrate / 2);
429 printf("VCM 1 sec: Bit rate: %u\tFrame rate: %u\n", bitRate, frameRate);
433 int32_t KeyFrameReqTest::RequestKeyFrame() {
434 printf("Key frame requested\n");
439 VideoProtectionCallback::VideoProtectionCallback():
443 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
444 memset(&key_fec_params_, 0, sizeof(key_fec_params_));
447 VideoProtectionCallback::~VideoProtectionCallback()
453 VideoProtectionCallback::ProtectionRequest(
454 const FecProtectionParams* delta_fec_params,
455 const FecProtectionParams* key_fec_params,
456 uint32_t* sent_video_rate_bps,
457 uint32_t* sent_nack_rate_bps,
458 uint32_t* sent_fec_rate_bps)
460 key_fec_params_ = *key_fec_params;
461 delta_fec_params_ = *delta_fec_params;
464 if (_rtp->SetFecParameters(&delta_fec_params_,
465 &key_fec_params_) != 0)
467 printf("Error in Setting FEC rate\n");
475 FecProtectionParams VideoProtectionCallback::DeltaFecParameters() const
477 return delta_fec_params_;
480 FecProtectionParams VideoProtectionCallback::KeyFecParameters() const
482 return key_fec_params_;
484 } // namespace webrtc