• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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