Home | History | Annotate | Download | only in test
      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