OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/modules/video_coding/packet_buffer.h" | |
12 | |
13 #include <algorithm> | |
14 #include <limits> | |
15 | |
16 #include "webrtc/base/mod_ops.h" | |
17 #include "webrtc/base/checks.h" | |
18 #include "webrtc/modules/video_coding/frame_object.h" | |
19 | |
20 namespace webrtc { | |
21 namespace video_coding { | |
22 | |
23 PacketBuffer::PacketBuffer(int start_buffer_size, | |
24 int max_buffer_size, | |
25 OnCompleteFrameCallback* frame_callback) : | |
26 size_(start_buffer_size), | |
27 max_size_(max_buffer_size), | |
28 clear_up_to_(0), | |
29 initialized_(false), | |
30 data_buffer_(start_buffer_size), | |
31 sequence_buffer_(start_buffer_size), | |
32 frame_callback_(frame_callback) { | |
33 RTC_DCHECK_LE(start_buffer_size, max_buffer_size); | |
stefan-webrtc
2016/03/17 12:06:31
Indentation, will probably be fixed with git cl fo
philipel
2016/03/17 15:00:35
Formated, lets hope for the best :)
| |
34 // Buffer size must always be a power of 2. | |
35 RTC_DCHECK((start_buffer_size & start_buffer_size - 1) == 0); | |
36 RTC_DCHECK((max_buffer_size & max_buffer_size - 1) == 0); | |
37 } | |
38 | |
39 bool PacketBuffer::InsertPacket(const VCMPacket& packet) { | |
40 rtc::CritScope lock(&crit_); | |
41 uint16_t seq_num = packet.seqNum; | |
42 int index = seq_num % size_; | |
43 | |
44 if (!initialized_) { | |
45 clear_up_to_ = seq_num; | |
46 initialized_ = true; | |
47 } | |
48 | |
49 if (sequence_buffer_[index].used) { | |
50 // Duplicate packet, do nothing. | |
51 if (data_buffer_[index].seqNum == packet.seqNum) | |
52 return false; | |
53 | |
54 // The Packet Buffer is full, try to expand the buffer. | |
stefan-webrtc
2016/03/17 12:06:31
PacketBuffer or "packet buffer"
philipel
2016/03/17 15:00:35
Done.
| |
55 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {} | |
56 index = seq_num % size_; | |
57 // If still full, test if the old packet can be discarded (overwritten | |
58 // later in the code), if not, return false. | |
59 if (sequence_buffer_[index].used && | |
60 AheadOrAt(sequence_buffer_[index].seq_num, clear_up_to_)) | |
61 return false; | |
62 } | |
63 | |
64 sequence_buffer_[index].frame_begin = packet.isFirstPacket; | |
65 sequence_buffer_[index].frame_end = packet.markerBit; | |
66 sequence_buffer_[index].seq_num = packet.seqNum; | |
67 sequence_buffer_[index].continuous = false; | |
68 sequence_buffer_[index].used = true; | |
69 data_buffer_[index] = packet; | |
70 | |
71 FindCompleteFrames(seq_num); | |
72 return true; | |
73 } | |
74 | |
75 void PacketBuffer::ClearUpTo(uint16_t seq_num) { | |
76 rtc::CritScope lock(&crit_); | |
77 clear_up_to_ = seq_num; | |
78 } | |
79 | |
80 bool PacketBuffer::ExpandBufferSize() { | |
81 if (size_ == max_size_) { | |
82 return false; | |
83 } | |
84 | |
85 int new_size = std::min(max_size_, 2*size_); | |
86 std::vector<VCMPacket> new_data_buffer(new_size); | |
87 std::vector<ContinuityInfo> new_sequence_buffer(new_size); | |
88 for (int i = 0; i < size_; ++i) { | |
89 if (sequence_buffer_[i].used) { | |
90 int index = sequence_buffer_[i].seq_num % new_size; | |
91 new_sequence_buffer[index] = sequence_buffer_[i]; | |
92 new_data_buffer[index] = data_buffer_[i]; | |
93 } | |
94 } | |
95 size_ = new_size; | |
96 sequence_buffer_ = std::move(new_sequence_buffer); | |
97 data_buffer_ = std::move(new_data_buffer); | |
98 return true; | |
99 } | |
100 | |
101 bool PacketBuffer::IsContinous(uint16_t seq_num) const { | |
102 int index = seq_num % size_; | |
103 int prev_index = index > 0 ? index - 1 : size_- 1; | |
104 if (!sequence_buffer_[index].used) | |
105 return false; | |
106 if (sequence_buffer_[index].frame_begin) | |
107 return true; | |
108 if (!sequence_buffer_[prev_index].used) | |
109 return false; | |
110 if (sequence_buffer_[prev_index].continuous) | |
111 return true; | |
112 | |
113 return false; | |
114 } | |
115 | |
116 void PacketBuffer::FindCompleteFrames(uint16_t seq_num) { | |
117 int index = seq_num % size_; | |
118 while (IsContinous(seq_num)) { | |
stefan-webrtc
2016/03/17 12:06:31
Do we always have to deliver continuous frames (ba
philipel
2016/03/17 15:00:35
This function only test the continuity between pac
| |
119 sequence_buffer_[index].continuous = true; | |
120 | |
121 // If the frame is complete, find the first packet of the frame and | |
122 // create a FrameObject. | |
123 if (sequence_buffer_[index].frame_end) { | |
124 int rindex = index; | |
125 uint16_t start_seq_num = seq_num; | |
126 while (!sequence_buffer_[rindex].frame_begin) { | |
127 rindex = rindex > 0 ? rindex - 1 : size_ - 1; | |
128 start_seq_num--; | |
129 } | |
130 | |
131 std::unique_ptr<FrameObject> frame( | |
132 new RtpFrameObject(this, start_seq_num, seq_num)); | |
133 frame_callback_->OnCompleteFrame(std::move(frame)); | |
134 } | |
135 | |
136 index = (index + 1) % size_; | |
137 ++seq_num; | |
138 } | |
139 } | |
140 | |
141 void PacketBuffer::Flush() { | |
142 rtc::CritScope lock(&crit_); | |
143 for (int i = 0; i < size_; ++i) { | |
144 sequence_buffer_[i].used = false; | |
145 sequence_buffer_[i].continuous = false; | |
146 } | |
147 } | |
148 | |
149 } // namespace video_coding | |
150 } // namespace webrtc | |
OLD | NEW |