diff options
Diffstat (limited to 'chromium/media/cast/rtp_sender/packet_storage/packet_storage.cc')
-rw-r--r-- | chromium/media/cast/rtp_sender/packet_storage/packet_storage.cc | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/chromium/media/cast/rtp_sender/packet_storage/packet_storage.cc b/chromium/media/cast/rtp_sender/packet_storage/packet_storage.cc new file mode 100644 index 00000000000..9c2d7ff0884 --- /dev/null +++ b/chromium/media/cast/rtp_sender/packet_storage/packet_storage.cc @@ -0,0 +1,141 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/cast/rtp_sender/packet_storage/packet_storage.h" + +#include <string> + +#include "base/logging.h" +#include "media/cast/cast_config.h" +#include "media/cast/cast_defines.h" + +namespace media { +namespace cast { + +// Limit the max time delay to avoid frame id wrap around; 256 / 60 fps. +const int kMaxAllowedTimeStoredMs = 4000; + +typedef PacketMap::iterator PacketMapIterator; +typedef TimeToPacketMap::iterator TimeToPacketIterator; + +class StoredPacket { + public: + StoredPacket() { + packet_.reserve(kIpPacketSize); + } + + void Save(const std::vector<uint8>& packet) { + DCHECK_LT(packet.size(), kIpPacketSize) << "Invalid argument"; + packet_.clear(); + packet_.insert(packet_.begin(), packet.begin(), packet.end()); + } + + void GetCopy(std::vector<uint8>* packet) { + packet->insert(packet->begin(), packet_.begin(), packet_.end()); + } + + private: + std::vector<uint8> packet_; +}; + + +PacketStorage::PacketStorage(int max_time_stored_ms) + : default_tick_clock_(new base::DefaultTickClock()), + clock_(default_tick_clock_.get()) { + max_time_stored_ = base::TimeDelta::FromMilliseconds(max_time_stored_ms); + DCHECK_LE(max_time_stored_ms, kMaxAllowedTimeStoredMs) << "Invalid argument"; +} + +PacketStorage::~PacketStorage() { + time_to_packet_map_.clear(); + + PacketMapIterator store_it = stored_packets_.begin(); + for (; store_it != stored_packets_.end(); + store_it = stored_packets_.begin()) { + stored_packets_.erase(store_it); + } + while (!free_packets_.empty()) { + free_packets_.pop_front(); + } +} + +void PacketStorage::CleanupOldPackets(base::TimeTicks now) { + TimeToPacketIterator time_it = time_to_packet_map_.begin(); + + // Check max size. + while (time_to_packet_map_.size() >= kMaxStoredPackets) { + PacketMapIterator store_it = stored_packets_.find(time_it->second); + + // We should always find the packet. + DCHECK(store_it != stored_packets_.end()) << "Invalid state"; + time_to_packet_map_.erase(time_it); + // Save the pointer. + linked_ptr<StoredPacket> storted_packet = store_it->second; + stored_packets_.erase(store_it); + // Add this packet to the free list for later re-use. + free_packets_.push_back(storted_packet); + time_it = time_to_packet_map_.begin(); + } + + // Time out old packets. + while (time_it != time_to_packet_map_.end()) { + if (now < time_it->first + max_time_stored_) { + break; + } + // Packet too old. + PacketMapIterator store_it = stored_packets_.find(time_it->second); + + // We should always find the packet. + DCHECK(store_it != stored_packets_.end()) << "Invalid state"; + time_to_packet_map_.erase(time_it); + // Save the pointer. + linked_ptr<StoredPacket> storted_packet = store_it->second; + stored_packets_.erase(store_it); + // Add this packet to the free list for later re-use. + free_packets_.push_back(storted_packet); + time_it = time_to_packet_map_.begin(); + } +} + +void PacketStorage::StorePacket(uint8 frame_id, + uint16 packet_id, + const std::vector<uint8>& packet) { + base::TimeTicks now = clock_->NowTicks(); + CleanupOldPackets(now); + + uint32 index = (static_cast<uint32>(frame_id) << 16) + packet_id; + PacketMapIterator it = stored_packets_.find(index); + if (it != stored_packets_.end()) { + // We have already saved this. + DCHECK(false) << "Invalid state"; + return; + } + linked_ptr<StoredPacket> stored_packet; + if (free_packets_.empty()) { + // No previous allocated packets allocate one. + stored_packet.reset(new StoredPacket()); + } else { + // Re-use previous allocated packet. + stored_packet = free_packets_.front(); + free_packets_.pop_front(); + } + stored_packet->Save(packet); + stored_packets_[index] = stored_packet; + time_to_packet_map_.insert(std::make_pair(now, index)); +} + +bool PacketStorage::GetPacket(uint8 frame_id, + uint16 packet_id, + std::vector<uint8>* packet) { + uint32 index = (static_cast<uint32>(frame_id) << 16) + packet_id; + PacketMapIterator it = stored_packets_.find(index); + if (it == stored_packets_.end()) { + return false; + } + it->second->GetCopy(packet); + return true; +} + +} // namespace cast +} // namespace media |