Home | History | Annotate | Download | only in rtp
      1 // Copyright 2014 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/net/rtp/frame_buffer.h"
      6 
      7 #include "base/logging.h"
      8 
      9 namespace media {
     10 namespace cast {
     11 
     12 FrameBuffer::FrameBuffer()
     13     : frame_id_(0),
     14       max_packet_id_(0),
     15       num_packets_received_(0),
     16       max_seen_packet_id_(0),
     17       new_playout_delay_ms_(0),
     18       is_key_frame_(false),
     19       total_data_size_(0),
     20       last_referenced_frame_id_(0),
     21       packets_() {}
     22 
     23 FrameBuffer::~FrameBuffer() {}
     24 
     25 bool FrameBuffer::InsertPacket(const uint8* payload_data,
     26                                size_t payload_size,
     27                                const RtpCastHeader& rtp_header) {
     28   // Is this the first packet in the frame?
     29   if (packets_.empty()) {
     30     frame_id_ = rtp_header.frame_id;
     31     max_packet_id_ = rtp_header.max_packet_id;
     32     is_key_frame_ = rtp_header.is_key_frame;
     33     new_playout_delay_ms_ = rtp_header.new_playout_delay_ms;
     34     if (is_key_frame_)
     35       DCHECK_EQ(rtp_header.frame_id, rtp_header.reference_frame_id);
     36     last_referenced_frame_id_ = rtp_header.reference_frame_id;
     37     rtp_timestamp_ = rtp_header.rtp_timestamp;
     38   }
     39   // Is this the correct frame?
     40   if (rtp_header.frame_id != frame_id_)
     41     return false;
     42 
     43   // Insert every packet only once.
     44   if (packets_.find(rtp_header.packet_id) != packets_.end()) {
     45     return false;
     46   }
     47 
     48   std::vector<uint8> data;
     49   std::pair<PacketMap::iterator, bool> retval =
     50       packets_.insert(make_pair(rtp_header.packet_id, data));
     51 
     52   // Insert the packet.
     53   retval.first->second.resize(payload_size);
     54   std::copy(
     55       payload_data, payload_data + payload_size, retval.first->second.begin());
     56 
     57   ++num_packets_received_;
     58   max_seen_packet_id_ = std::max(max_seen_packet_id_, rtp_header.packet_id);
     59   total_data_size_ += payload_size;
     60   return true;
     61 }
     62 
     63 bool FrameBuffer::Complete() const {
     64   return num_packets_received_ - 1 == max_packet_id_;
     65 }
     66 
     67 bool FrameBuffer::AssembleEncodedFrame(EncodedFrame* frame) const {
     68   if (!Complete())
     69     return false;
     70 
     71   // Frame is complete -> construct.
     72   if (is_key_frame_)
     73     frame->dependency = EncodedFrame::KEY;
     74   else if (frame_id_ == last_referenced_frame_id_)
     75     frame->dependency = EncodedFrame::INDEPENDENT;
     76   else
     77     frame->dependency = EncodedFrame::DEPENDENT;
     78   frame->frame_id = frame_id_;
     79   frame->referenced_frame_id = last_referenced_frame_id_;
     80   frame->rtp_timestamp = rtp_timestamp_;
     81   frame->new_playout_delay_ms = new_playout_delay_ms_;
     82 
     83   // Build the data vector.
     84   frame->data.clear();
     85   frame->data.reserve(total_data_size_);
     86   PacketMap::const_iterator it;
     87   for (it = packets_.begin(); it != packets_.end(); ++it)
     88     frame->data.insert(frame->data.end(), it->second.begin(), it->second.end());
     89   return true;
     90 }
     91 
     92 void FrameBuffer::GetMissingPackets(bool newest_frame,
     93                                     PacketIdSet* missing_packets) const {
     94   // Missing packets capped by max_seen_packet_id_.
     95   // (Iff it's the latest frame)
     96   int maximum = newest_frame ? max_seen_packet_id_ : max_packet_id_;
     97   int packet = 0;
     98   for (PacketMap::const_iterator i = packets_.begin();
     99        i != packets_.end() && packet <= maximum;
    100        ++i) {
    101     int end = std::min<int>(i->first, maximum + 1);
    102     while (packet < end) {
    103       missing_packets->insert(packet);
    104       packet++;
    105     }
    106     packet++;
    107   }
    108   while (packet <= maximum) {
    109     missing_packets->insert(packet);
    110     packet++;
    111   }
    112 }
    113 
    114 
    115 }  // namespace cast
    116 }  // namespace media
    117