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
VCMEncodeCompleteCallback(FILE * encodedFile)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 }
~VCMEncodeCompleteCallback()43 VCMEncodeCompleteCallback::~VCMEncodeCompleteCallback()
44 {
45 }
46
47 void
RegisterTransportCallback(VCMPacketizationCallback * transport)48 VCMEncodeCompleteCallback::RegisterTransportCallback(
49 VCMPacketizationCallback* transport)
50 {
51 }
52
53 int32_t
SendData(const FrameType frameType,const uint8_t payloadType,const uint32_t timeStamp,int64_t capture_time_ms,const uint8_t * payloadData,const uint32_t payloadSize,const RTPFragmentationHeader & fragmentationHeader,const RTPVideoHeader * videoHdr)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
EncodedBytes()107 VCMEncodeCompleteCallback::EncodedBytes()
108 {
109 return _encodedBytes;
110 }
111
112 bool
EncodeComplete()113 VCMEncodeCompleteCallback::EncodeComplete()
114 {
115 if (_encodeComplete)
116 {
117 _encodeComplete = false;
118 return true;
119 }
120 return false;
121 }
122
123 void
Initialize()124 VCMEncodeCompleteCallback::Initialize()
125 {
126 _encodeComplete = false;
127 _encodedBytes = 0;
128 _seqNo = 0;
129 return;
130 }
131
132 void
ResetByteCount()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
SendData(const FrameType frameType,const uint8_t payloadType,const uint32_t timeStamp,int64_t capture_time_ms,const uint8_t * payloadData,const uint32_t payloadSize,const RTPFragmentationHeader & fragmentationHeader,const RTPVideoHeader * videoHdr)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
EncodedBytes()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
EncodeComplete()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
FrameToRender(I420VideoFrame & videoFrame)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
DecodedBytes()203 VCMDecodeCompleteCallback::DecodedBytes()
204 {
205 return _decodedBytes;
206 }
207
RTPSendCompleteCallback(Clock * clock,const char * filename)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
~RTPSendCompleteCallback()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
SendPacket(int channel,const void * data,int len)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
SendRTCPPacket(int channel,const void * data,int len)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
SetLossPct(double lossPct)330 RTPSendCompleteCallback::SetLossPct(double lossPct)
331 {
332 _lossPct = lossPct;
333 return;
334 }
335
336 void
SetBurstLength(double burstLength)337 RTPSendCompleteCallback::SetBurstLength(double burstLength)
338 {
339 _burstLength = burstLength;
340 return;
341 }
342
343 bool
PacketLoss()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
UnifomLoss(double lossPct)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
ResendPackets(const uint16_t * sequenceNumbers,uint16_t length)414 PacketRequester::ResendPackets(const uint16_t* sequenceNumbers,
415 uint16_t length)
416 {
417 return _rtp.SendNACK(sequenceNumbers, length);
418 }
419
420 int32_t
SendStatistics(const uint32_t bitRate,const uint32_t frameRate)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
RequestKeyFrame()430 int32_t KeyFrameReqTest::RequestKeyFrame() {
431 printf("Key frame requested\n");
432 return 0;
433 }
434
435
VideoProtectionCallback()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
~VideoProtectionCallback()444 VideoProtectionCallback::~VideoProtectionCallback()
445 {
446 //
447 }
448
449 int32_t
ProtectionRequest(const FecProtectionParams * delta_fec_params,const FecProtectionParams * key_fec_params,uint32_t * sent_video_rate_bps,uint32_t * sent_nack_rate_bps,uint32_t * sent_fec_rate_bps)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
DeltaFecParameters() const472 FecProtectionParams VideoProtectionCallback::DeltaFecParameters() const
473 {
474 return delta_fec_params_;
475 }
476
KeyFecParameters() const477 FecProtectionParams VideoProtectionCallback::KeyFecParameters() const
478 {
479 return key_fec_params_;
480 }
481 } // namespace webrtc
482