/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/video_coding/codecs/test/packet_manipulator.h" #include #include namespace webrtc { namespace test { PacketManipulatorImpl::PacketManipulatorImpl(PacketReader* packet_reader, const NetworkingConfig& config, bool verbose) : packet_reader_(packet_reader), config_(config), active_burst_packets_(0), verbose_(verbose) { assert(packet_reader); } PacketManipulatorImpl::~PacketManipulatorImpl() { } int PacketManipulatorImpl::ManipulatePackets( webrtc::EncodedImage* encoded_image) { assert(encoded_image); int nbr_packets_dropped = 0; // There's no need to build a copy of the image data since viewing an // EncodedImage object, setting the length to a new lower value represents // that everything is dropped after that position in the byte array. // EncodedImage._size is the allocated bytes. // EncodedImage._length is how many that are filled with data. int new_length = 0; packet_reader_->InitializeReading(encoded_image->_buffer, encoded_image->_length, config_.packet_size_in_bytes); WebRtc_UWord8* packet = NULL; int nbr_bytes_to_read; // keep track of if we've lost any packets, since then we shall loose // the remains of the current frame: bool packet_loss_has_occurred = false; while ((nbr_bytes_to_read = packet_reader_->NextPacket(&packet)) > 0) { // Check if we're currently in a packet loss burst that is not completed: if (active_burst_packets_ > 0) { active_burst_packets_--; nbr_packets_dropped++; } else if (RandomUniform() < config_.packet_loss_probability || packet_loss_has_occurred) { packet_loss_has_occurred = true; nbr_packets_dropped++; if (config_.packet_loss_mode == kBurst) { // Initiate a new burst active_burst_packets_ = config_.packet_loss_burst_length - 1; } } else { new_length += nbr_bytes_to_read; } } encoded_image->_length = new_length; if (nbr_packets_dropped > 0) { // Must set completeFrame to false to inform the decoder about this: encoded_image->_completeFrame = false; if (verbose_) { printf("Dropped %d packets for frame %d (frame length: %d)\n", nbr_packets_dropped, encoded_image->_timeStamp, encoded_image->_length); } } return nbr_packets_dropped; } inline double PacketManipulatorImpl::RandomUniform() { return (std::rand() + 1.0)/(RAND_MAX + 1.0); } const char* PacketLossModeToStr(PacketLossMode e) { switch (e) { case kUniform: return "Uniform"; case kBurst: return "Burst"; default: assert(false); return "Unknown"; } } } // namespace test } // namespace webrtcc