• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FrameBuffer()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 
~FrameBuffer()23 FrameBuffer::~FrameBuffer() {}
24 
InsertPacket(const uint8 * payload_data,size_t payload_size,const RtpCastHeader & rtp_header)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 
Complete() const63 bool FrameBuffer::Complete() const {
64   return num_packets_received_ - 1 == max_packet_id_;
65 }
66 
AssembleEncodedFrame(EncodedFrame * frame) const67 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 
GetMissingPackets(bool newest_frame,PacketIdSet * missing_packets) const92 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