Line data Source code
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 : #include <utility>
16 :
17 : #include "webrtc/base/atomicops.h"
18 : #include "webrtc/base/checks.h"
19 : #include "webrtc/base/logging.h"
20 : #include "webrtc/modules/video_coding/frame_object.h"
21 : #include "webrtc/system_wrappers/include/clock.h"
22 :
23 : namespace webrtc {
24 : namespace video_coding {
25 :
26 0 : rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create(
27 : Clock* clock,
28 : size_t start_buffer_size,
29 : size_t max_buffer_size,
30 : OnReceivedFrameCallback* received_frame_callback) {
31 : return rtc::scoped_refptr<PacketBuffer>(new PacketBuffer(
32 0 : clock, start_buffer_size, max_buffer_size, received_frame_callback));
33 : }
34 :
35 0 : PacketBuffer::PacketBuffer(Clock* clock,
36 : size_t start_buffer_size,
37 : size_t max_buffer_size,
38 0 : OnReceivedFrameCallback* received_frame_callback)
39 : : clock_(clock),
40 : size_(start_buffer_size),
41 : max_size_(max_buffer_size),
42 : first_seq_num_(0),
43 : first_packet_received_(false),
44 : is_cleared_to_first_seq_num_(false),
45 : data_buffer_(start_buffer_size),
46 : sequence_buffer_(start_buffer_size),
47 0 : received_frame_callback_(received_frame_callback) {
48 0 : RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
49 : // Buffer size must always be a power of 2.
50 0 : RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
51 0 : RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
52 0 : }
53 :
54 0 : PacketBuffer::~PacketBuffer() {
55 0 : Clear();
56 0 : }
57 :
58 0 : bool PacketBuffer::InsertPacket(VCMPacket* packet) {
59 0 : std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
60 : {
61 0 : rtc::CritScope lock(&crit_);
62 0 : uint16_t seq_num = packet->seqNum;
63 0 : size_t index = seq_num % size_;
64 :
65 0 : if (!first_packet_received_) {
66 0 : first_seq_num_ = seq_num;
67 0 : first_packet_received_ = true;
68 0 : } else if (AheadOf(first_seq_num_, seq_num)) {
69 : // If we have explicitly cleared past this packet then it's old,
70 : // don't insert it.
71 0 : if (is_cleared_to_first_seq_num_) {
72 0 : delete[] packet->dataPtr;
73 0 : packet->dataPtr = nullptr;
74 0 : return false;
75 : }
76 :
77 0 : first_seq_num_ = seq_num;
78 : }
79 :
80 0 : if (sequence_buffer_[index].used) {
81 : // Duplicate packet, just delete the payload.
82 0 : if (data_buffer_[index].seqNum == packet->seqNum) {
83 0 : delete[] packet->dataPtr;
84 0 : packet->dataPtr = nullptr;
85 0 : return true;
86 : }
87 :
88 : // The packet buffer is full, try to expand the buffer.
89 0 : while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
90 : }
91 0 : index = seq_num % size_;
92 :
93 : // Packet buffer is still full.
94 0 : if (sequence_buffer_[index].used) {
95 0 : delete[] packet->dataPtr;
96 0 : packet->dataPtr = nullptr;
97 0 : return false;
98 : }
99 : }
100 :
101 0 : sequence_buffer_[index].frame_begin = packet->is_first_packet_in_frame;
102 0 : sequence_buffer_[index].frame_end = packet->markerBit;
103 0 : sequence_buffer_[index].seq_num = packet->seqNum;
104 0 : sequence_buffer_[index].continuous = false;
105 0 : sequence_buffer_[index].frame_created = false;
106 0 : sequence_buffer_[index].used = true;
107 0 : data_buffer_[index] = *packet;
108 0 : packet->dataPtr = nullptr;
109 :
110 0 : found_frames = FindFrames(seq_num);
111 : }
112 :
113 0 : for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
114 0 : received_frame_callback_->OnReceivedFrame(std::move(frame));
115 :
116 0 : return true;
117 : }
118 :
119 0 : void PacketBuffer::ClearTo(uint16_t seq_num) {
120 0 : rtc::CritScope lock(&crit_);
121 :
122 : // If the packet buffer was cleared between a frame was created and returned.
123 0 : if (!first_packet_received_)
124 0 : return;
125 :
126 0 : is_cleared_to_first_seq_num_ = true;
127 0 : while (AheadOrAt<uint16_t>(seq_num, first_seq_num_)) {
128 0 : size_t index = first_seq_num_ % size_;
129 0 : delete[] data_buffer_[index].dataPtr;
130 0 : data_buffer_[index].dataPtr = nullptr;
131 0 : sequence_buffer_[index].used = false;
132 0 : ++first_seq_num_;
133 : }
134 : }
135 :
136 0 : void PacketBuffer::Clear() {
137 0 : rtc::CritScope lock(&crit_);
138 0 : for (size_t i = 0; i < size_; ++i) {
139 0 : delete[] data_buffer_[i].dataPtr;
140 0 : data_buffer_[i].dataPtr = nullptr;
141 0 : sequence_buffer_[i].used = false;
142 : }
143 :
144 0 : first_packet_received_ = false;
145 0 : is_cleared_to_first_seq_num_ = false;
146 0 : }
147 :
148 0 : bool PacketBuffer::ExpandBufferSize() {
149 0 : if (size_ == max_size_) {
150 0 : LOG(LS_WARNING) << "PacketBuffer is already at max size (" << max_size_
151 0 : << "), failed to increase size.";
152 0 : return false;
153 : }
154 :
155 0 : size_t new_size = std::min(max_size_, 2 * size_);
156 0 : std::vector<VCMPacket> new_data_buffer(new_size);
157 0 : std::vector<ContinuityInfo> new_sequence_buffer(new_size);
158 0 : for (size_t i = 0; i < size_; ++i) {
159 0 : if (sequence_buffer_[i].used) {
160 0 : size_t index = sequence_buffer_[i].seq_num % new_size;
161 0 : new_sequence_buffer[index] = sequence_buffer_[i];
162 0 : new_data_buffer[index] = data_buffer_[i];
163 : }
164 : }
165 0 : size_ = new_size;
166 0 : sequence_buffer_ = std::move(new_sequence_buffer);
167 0 : data_buffer_ = std::move(new_data_buffer);
168 0 : LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
169 0 : return true;
170 : }
171 :
172 0 : bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
173 0 : size_t index = seq_num % size_;
174 0 : int prev_index = index > 0 ? index - 1 : size_ - 1;
175 :
176 0 : if (!sequence_buffer_[index].used)
177 0 : return false;
178 0 : if (sequence_buffer_[index].frame_created)
179 0 : return false;
180 0 : if (sequence_buffer_[index].frame_begin)
181 0 : return true;
182 0 : if (!sequence_buffer_[prev_index].used)
183 0 : return false;
184 0 : if (sequence_buffer_[prev_index].frame_created)
185 0 : return false;
186 0 : if (sequence_buffer_[prev_index].seq_num !=
187 0 : static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
188 0 : return false;
189 : }
190 0 : if (sequence_buffer_[prev_index].continuous)
191 0 : return true;
192 :
193 0 : return false;
194 : }
195 :
196 0 : std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
197 : uint16_t seq_num) {
198 0 : std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
199 0 : size_t packets_tested = 0;
200 0 : while (packets_tested < size_ && PotentialNewFrame(seq_num)) {
201 0 : size_t index = seq_num % size_;
202 0 : sequence_buffer_[index].continuous = true;
203 :
204 : // If all packets of the frame is continuous, find the first packet of the
205 : // frame and create an RtpFrameObject.
206 0 : if (sequence_buffer_[index].frame_end) {
207 0 : size_t frame_size = 0;
208 0 : int max_nack_count = -1;
209 0 : uint16_t start_seq_num = seq_num;
210 :
211 : // Find the start index by searching backward until the packet with
212 : // the |frame_begin| flag is set.
213 0 : int start_index = index;
214 : while (true) {
215 0 : frame_size += data_buffer_[start_index].sizeBytes;
216 0 : max_nack_count =
217 0 : std::max(max_nack_count, data_buffer_[start_index].timesNacked);
218 0 : sequence_buffer_[start_index].frame_created = true;
219 :
220 0 : if (sequence_buffer_[start_index].frame_begin)
221 0 : break;
222 :
223 0 : start_index = start_index > 0 ? start_index - 1 : size_ - 1;
224 0 : start_seq_num--;
225 : }
226 :
227 : found_frames.emplace_back(
228 0 : new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
229 0 : max_nack_count, clock_->TimeInMilliseconds()));
230 : }
231 0 : ++seq_num;
232 0 : ++packets_tested;
233 : }
234 0 : return found_frames;
235 : }
236 :
237 0 : void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
238 0 : rtc::CritScope lock(&crit_);
239 0 : size_t index = frame->first_seq_num() % size_;
240 0 : size_t end = (frame->last_seq_num() + 1) % size_;
241 0 : uint16_t seq_num = frame->first_seq_num();
242 0 : while (index != end) {
243 0 : if (sequence_buffer_[index].seq_num == seq_num) {
244 0 : delete[] data_buffer_[index].dataPtr;
245 0 : data_buffer_[index].dataPtr = nullptr;
246 0 : sequence_buffer_[index].used = false;
247 : }
248 :
249 0 : index = (index + 1) % size_;
250 0 : ++seq_num;
251 : }
252 0 : }
253 :
254 0 : bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
255 : uint8_t* destination) {
256 0 : rtc::CritScope lock(&crit_);
257 :
258 0 : size_t index = frame.first_seq_num() % size_;
259 0 : size_t end = (frame.last_seq_num() + 1) % size_;
260 0 : uint16_t seq_num = frame.first_seq_num();
261 0 : while (index != end) {
262 0 : if (!sequence_buffer_[index].used ||
263 0 : sequence_buffer_[index].seq_num != seq_num) {
264 0 : return false;
265 : }
266 :
267 0 : const uint8_t* source = data_buffer_[index].dataPtr;
268 0 : size_t length = data_buffer_[index].sizeBytes;
269 0 : memcpy(destination, source, length);
270 0 : destination += length;
271 0 : index = (index + 1) % size_;
272 0 : ++seq_num;
273 : }
274 0 : return true;
275 : }
276 :
277 0 : VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
278 0 : size_t index = seq_num % size_;
279 0 : if (!sequence_buffer_[index].used ||
280 0 : seq_num != sequence_buffer_[index].seq_num) {
281 0 : return nullptr;
282 : }
283 0 : return &data_buffer_[index];
284 : }
285 :
286 0 : int PacketBuffer::AddRef() const {
287 0 : return rtc::AtomicOps::Increment(&ref_count_);
288 : }
289 :
290 0 : int PacketBuffer::Release() const {
291 0 : int count = rtc::AtomicOps::Decrement(&ref_count_);
292 0 : if (!count) {
293 0 : delete this;
294 : }
295 0 : return count;
296 : }
297 :
298 : } // namespace video_coding
299 : } // namespace webrtc
|