Home | History | Annotate | Download | only in rtp_sender
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/cast/transport/rtp_sender/rtp_sender.h"
      6 
      7 #include "base/big_endian.h"
      8 #include "base/logging.h"
      9 #include "base/rand_util.h"
     10 #include "media/cast/transport/cast_transport_defines.h"
     11 #include "media/cast/transport/pacing/paced_sender.h"
     12 
     13 namespace media {
     14 namespace cast {
     15 namespace transport {
     16 
     17 namespace {
     18 
     19 // If there is only one referecne to the packet then copy the
     20 // reference and return.
     21 // Otherwise return a deep copy of the packet.
     22 PacketRef FastCopyPacket(const PacketRef& packet) {
     23   if (packet->HasOneRef())
     24     return packet;
     25   return make_scoped_refptr(new base::RefCountedData<Packet>(packet->data));
     26 }
     27 
     28 }  // namespace
     29 
     30 RtpSender::RtpSender(
     31     base::TickClock* clock,
     32     const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner,
     33     PacedSender* const transport)
     34     : clock_(clock),
     35       transport_(transport),
     36       transport_task_runner_(transport_task_runner),
     37       weak_factory_(this) {
     38   // Randomly set sequence number start value.
     39   config_.sequence_number = base::RandInt(0, 65535);
     40 }
     41 
     42 RtpSender::~RtpSender() {}
     43 
     44 bool RtpSender::InitializeAudio(const CastTransportAudioConfig& config) {
     45   storage_.reset(new PacketStorage(config.rtp.max_outstanding_frames));
     46   if (!storage_->IsValid()) {
     47     return false;
     48   }
     49   config_.audio = true;
     50   config_.ssrc = config.rtp.config.ssrc;
     51   config_.payload_type = config.rtp.config.payload_type;
     52   config_.frequency = config.frequency;
     53   config_.audio_codec = config.codec;
     54   packetizer_.reset(new RtpPacketizer(transport_, storage_.get(), config_));
     55   return true;
     56 }
     57 
     58 bool RtpSender::InitializeVideo(const CastTransportVideoConfig& config) {
     59   storage_.reset(new PacketStorage(config.rtp.max_outstanding_frames));
     60   if (!storage_->IsValid()) {
     61     return false;
     62   }
     63   config_.audio = false;
     64   config_.ssrc = config.rtp.config.ssrc;
     65   config_.payload_type = config.rtp.config.payload_type;
     66   config_.frequency = kVideoFrequency;
     67   config_.video_codec = config.codec;
     68   packetizer_.reset(new RtpPacketizer(transport_, storage_.get(), config_));
     69   return true;
     70 }
     71 
     72 void RtpSender::SendFrame(const EncodedFrame& frame) {
     73   DCHECK(packetizer_);
     74   packetizer_->SendFrameAsPackets(frame);
     75 }
     76 
     77 void RtpSender::ResendPackets(
     78     const MissingFramesAndPacketsMap& missing_frames_and_packets,
     79     bool cancel_rtx_if_not_in_list,
     80     base::TimeDelta dedupe_window) {
     81   DCHECK(storage_);
     82   // Iterate over all frames in the list.
     83   for (MissingFramesAndPacketsMap::const_iterator it =
     84            missing_frames_and_packets.begin();
     85        it != missing_frames_and_packets.end();
     86        ++it) {
     87     SendPacketVector packets_to_resend;
     88     uint8 frame_id = it->first;
     89     // Set of packets that the receiver wants us to re-send.
     90     // If empty, we need to re-send all packets for this frame.
     91     const PacketIdSet& missing_packet_set = it->second;
     92 
     93     bool resend_all = missing_packet_set.find(kRtcpCastAllPacketsLost) !=
     94         missing_packet_set.end();
     95     bool resend_last = missing_packet_set.find(kRtcpCastLastPacket) !=
     96         missing_packet_set.end();
     97 
     98     const SendPacketVector* stored_packets = storage_->GetFrame8(frame_id);
     99     if (!stored_packets)
    100       continue;
    101 
    102     for (SendPacketVector::const_iterator it = stored_packets->begin();
    103          it != stored_packets->end(); ++it) {
    104       const PacketKey& packet_key = it->first;
    105       const uint16 packet_id = packet_key.second.second;
    106 
    107       // Should we resend the packet?
    108       bool resend = resend_all;
    109 
    110       // Should we resend it because it's in the missing_packet_set?
    111       if (!resend &&
    112           missing_packet_set.find(packet_id) != missing_packet_set.end()) {
    113         resend = true;
    114       }
    115 
    116       // If we were asked to resend the last packet, check if it's the
    117       // last packet.
    118       if (!resend && resend_last && (it + 1) == stored_packets->end()) {
    119         resend = true;
    120       }
    121 
    122       if (resend) {
    123         // Resend packet to the network.
    124         VLOG(3) << "Resend " << static_cast<int>(frame_id) << ":"
    125                 << packet_id;
    126         // Set a unique incremental sequence number for every packet.
    127         PacketRef packet_copy = FastCopyPacket(it->second);
    128         UpdateSequenceNumber(&packet_copy->data);
    129         packets_to_resend.push_back(std::make_pair(packet_key, packet_copy));
    130       } else if (cancel_rtx_if_not_in_list) {
    131         transport_->CancelSendingPacket(it->first);
    132       }
    133     }
    134     transport_->ResendPackets(packets_to_resend, dedupe_window);
    135   }
    136 }
    137 
    138 void RtpSender::UpdateSequenceNumber(Packet* packet) {
    139   // TODO(miu): This is an abstraction violation.  This needs to be a part of
    140   // the overall packet (de)serialization consolidation.
    141   static const int kByteOffsetToSequenceNumber = 2;
    142   base::BigEndianWriter big_endian_writer(
    143       reinterpret_cast<char*>((&packet->front()) + kByteOffsetToSequenceNumber),
    144       sizeof(uint16));
    145   big_endian_writer.WriteU16(packetizer_->NextSequenceNumber());
    146 }
    147 
    148 }  // namespace transport
    149 }  //  namespace cast
    150 }  // namespace media
    151