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/codecs/test/packet_manipulator.h"
     12 
     13 #include <assert.h>
     14 #include <stdio.h>
     15 
     16 namespace webrtc {
     17 namespace test {
     18 
     19 PacketManipulatorImpl::PacketManipulatorImpl(PacketReader* packet_reader,
     20                                              const NetworkingConfig& config,
     21                                              bool verbose)
     22     : packet_reader_(packet_reader),
     23       config_(config),
     24       active_burst_packets_(0),
     25       critsect_(CriticalSectionWrapper::CreateCriticalSection()),
     26       random_seed_(1),
     27       verbose_(verbose) {
     28   assert(packet_reader);
     29 }
     30 
     31 PacketManipulatorImpl::~PacketManipulatorImpl() {
     32   delete critsect_;
     33 }
     34 
     35 int PacketManipulatorImpl::ManipulatePackets(
     36     webrtc::EncodedImage* encoded_image) {
     37   assert(encoded_image);
     38   int nbr_packets_dropped = 0;
     39   // There's no need to build a copy of the image data since viewing an
     40   // EncodedImage object, setting the length to a new lower value represents
     41   // that everything is dropped after that position in the byte array.
     42   // EncodedImage._size is the allocated bytes.
     43   // EncodedImage._length is how many that are filled with data.
     44   int new_length = 0;
     45   packet_reader_->InitializeReading(encoded_image->_buffer,
     46                                     encoded_image->_length,
     47                                     config_.packet_size_in_bytes);
     48   uint8_t* packet = NULL;
     49   int nbr_bytes_to_read;
     50   // keep track of if we've lost any packets, since then we shall loose
     51   // the remains of the current frame:
     52   bool packet_loss_has_occurred = false;
     53   while ((nbr_bytes_to_read = packet_reader_->NextPacket(&packet)) > 0) {
     54     // Check if we're currently in a packet loss burst that is not completed:
     55     if (active_burst_packets_ > 0) {
     56       active_burst_packets_--;
     57       nbr_packets_dropped++;
     58     } else if (RandomUniform() < config_.packet_loss_probability ||
     59         packet_loss_has_occurred) {
     60       packet_loss_has_occurred = true;
     61       nbr_packets_dropped++;
     62       if (config_.packet_loss_mode == kBurst) {
     63         // Initiate a new burst
     64         active_burst_packets_ = config_.packet_loss_burst_length - 1;
     65       }
     66     } else {
     67       new_length += nbr_bytes_to_read;
     68     }
     69   }
     70   encoded_image->_length = new_length;
     71   if (nbr_packets_dropped > 0) {
     72     // Must set completeFrame to false to inform the decoder about this:
     73     encoded_image->_completeFrame = false;
     74     if (verbose_) {
     75       printf("Dropped %d packets for frame %d (frame length: %d)\n",
     76              nbr_packets_dropped, encoded_image->_timeStamp,
     77              encoded_image->_length);
     78     }
     79   }
     80   return nbr_packets_dropped;
     81 }
     82 
     83 void PacketManipulatorImpl::InitializeRandomSeed(unsigned int seed) {
     84   random_seed_ = seed;
     85 }
     86 
     87 inline double PacketManipulatorImpl::RandomUniform() {
     88   // Use the previous result as new seed before each rand() call. Doing this
     89   // it doesn't matter if other threads are calling rand() since we'll always
     90   // get the same behavior as long as we're using a fixed initial seed.
     91   critsect_->Enter();
     92   srand(random_seed_);
     93   random_seed_ = rand();
     94   critsect_->Leave();
     95   return (random_seed_ + 1.0)/(RAND_MAX + 1.0);
     96 }
     97 
     98 const char* PacketLossModeToStr(PacketLossMode e) {
     99   switch (e) {
    100     case kUniform:
    101       return "Uniform";
    102     case kBurst:
    103       return "Burst";
    104     default:
    105       assert(false);
    106       return "Unknown";
    107   }
    108 }
    109 
    110 }  // namespace test
    111 }  // namespace webrtcc
    112