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