blob: 7b9b659543707f0c307d64e042336991e05a1cb6 [file] [log] [blame]
philipelc707ab72016-04-01 02:01:54 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/video_coding/packet_buffer.h"
philipelc707ab72016-04-01 02:01:54 -070012
13#include <algorithm>
14#include <limits>
philipel17deeb42016-08-11 15:09:26 +020015#include <utility>
philipelc707ab72016-04-01 02:01:54 -070016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "common_video/h264/h264_common.h"
18#include "modules/video_coding/frame_object.h"
19#include "rtc_base/atomicops.h"
20#include "rtc_base/checks.h"
21#include "rtc_base/logging.h"
22#include "system_wrappers/include/clock.h"
philipelc707ab72016-04-01 02:01:54 -070023
24namespace webrtc {
25namespace video_coding {
26
philipel17deeb42016-08-11 15:09:26 +020027rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create(
28 Clock* clock,
29 size_t start_buffer_size,
30 size_t max_buffer_size,
31 OnReceivedFrameCallback* received_frame_callback) {
32 return rtc::scoped_refptr<PacketBuffer>(new PacketBuffer(
33 clock, start_buffer_size, max_buffer_size, received_frame_callback));
34}
35
philipelb4d31082016-07-11 08:46:29 -070036PacketBuffer::PacketBuffer(Clock* clock,
37 size_t start_buffer_size,
philipelc707ab72016-04-01 02:01:54 -070038 size_t max_buffer_size,
philipel17deeb42016-08-11 15:09:26 +020039 OnReceivedFrameCallback* received_frame_callback)
philipelb4d31082016-07-11 08:46:29 -070040 : clock_(clock),
41 size_(start_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070042 max_size_(max_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070043 first_seq_num_(0),
philipelf4139332016-04-20 10:26:34 +020044 first_packet_received_(false),
philipelaee3e0e2016-11-01 11:45:34 +010045 is_cleared_to_first_seq_num_(false),
philipelc707ab72016-04-01 02:01:54 -070046 data_buffer_(start_buffer_size),
47 sequence_buffer_(start_buffer_size),
philipel17deeb42016-08-11 15:09:26 +020048 received_frame_callback_(received_frame_callback) {
philipelc707ab72016-04-01 02:01:54 -070049 RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
50 // Buffer size must always be a power of 2.
51 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
52 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
53}
54
philipelaee3e0e2016-11-01 11:45:34 +010055PacketBuffer::~PacketBuffer() {
56 Clear();
57}
philipel17deeb42016-08-11 15:09:26 +020058
philipel759e0b72016-11-30 01:32:05 -080059bool PacketBuffer::InsertPacket(VCMPacket* packet) {
philipelfd5a20f2016-11-15 00:57:57 -080060 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
61 {
62 rtc::CritScope lock(&crit_);
philipel3184f8e2017-05-18 08:08:53 -070063
philipel759e0b72016-11-30 01:32:05 -080064 uint16_t seq_num = packet->seqNum;
philipelfd5a20f2016-11-15 00:57:57 -080065 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -070066
philipelfd5a20f2016-11-15 00:57:57 -080067 if (!first_packet_received_) {
68 first_seq_num_ = seq_num;
philipelfd5a20f2016-11-15 00:57:57 -080069 first_packet_received_ = true;
70 } else if (AheadOf(first_seq_num_, seq_num)) {
71 // If we have explicitly cleared past this packet then it's old,
72 // don't insert it.
philipel759e0b72016-11-30 01:32:05 -080073 if (is_cleared_to_first_seq_num_) {
74 delete[] packet->dataPtr;
75 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -080076 return false;
philipel759e0b72016-11-30 01:32:05 -080077 }
philipelaee3e0e2016-11-01 11:45:34 +010078
philipelfd5a20f2016-11-15 00:57:57 -080079 first_seq_num_ = seq_num;
philipelc707ab72016-04-01 02:01:54 -070080 }
philipelc707ab72016-04-01 02:01:54 -070081
philipelfd5a20f2016-11-15 00:57:57 -080082 if (sequence_buffer_[index].used) {
philipel759e0b72016-11-30 01:32:05 -080083 // Duplicate packet, just delete the payload.
84 if (data_buffer_[index].seqNum == packet->seqNum) {
85 delete[] packet->dataPtr;
86 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -080087 return true;
philipel759e0b72016-11-30 01:32:05 -080088 }
philipelfd5a20f2016-11-15 00:57:57 -080089
90 // The packet buffer is full, try to expand the buffer.
91 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
92 }
93 index = seq_num % size_;
94
95 // Packet buffer is still full.
philipel759e0b72016-11-30 01:32:05 -080096 if (sequence_buffer_[index].used) {
97 delete[] packet->dataPtr;
98 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -080099 return false;
philipel759e0b72016-11-30 01:32:05 -0800100 }
philipelfd5a20f2016-11-15 00:57:57 -0800101 }
102
johan0d1b2b62017-01-10 04:21:35 -0800103 sequence_buffer_[index].frame_begin = packet->is_first_packet_in_frame;
philipel759e0b72016-11-30 01:32:05 -0800104 sequence_buffer_[index].frame_end = packet->markerBit;
105 sequence_buffer_[index].seq_num = packet->seqNum;
philipelfd5a20f2016-11-15 00:57:57 -0800106 sequence_buffer_[index].continuous = false;
107 sequence_buffer_[index].frame_created = false;
108 sequence_buffer_[index].used = true;
philipel759e0b72016-11-30 01:32:05 -0800109 data_buffer_[index] = *packet;
110 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800111
philipel2c9f9f22017-06-13 02:47:28 -0700112 UpdateMissingPackets(packet->seqNum);
113
philipel3184f8e2017-05-18 08:08:53 -0700114 int64_t now_ms = clock_->TimeInMilliseconds();
115 last_received_packet_ms_ = rtc::Optional<int64_t>(now_ms);
116 if (packet->frameType == kVideoFrameKey)
117 last_received_keyframe_packet_ms_ = rtc::Optional<int64_t>(now_ms);
118
philipelfd5a20f2016-11-15 00:57:57 -0800119 found_frames = FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -0700120 }
121
philipelfd5a20f2016-11-15 00:57:57 -0800122 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
123 received_frame_callback_->OnReceivedFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700124
philipelc707ab72016-04-01 02:01:54 -0700125 return true;
126}
127
128void PacketBuffer::ClearTo(uint16_t seq_num) {
129 rtc::CritScope lock(&crit_);
philipelc5fb4682017-08-02 04:28:57 -0700130 // We have already cleared past this sequence number, no need to do anything.
131 if (is_cleared_to_first_seq_num_ &&
132 AheadOf<uint16_t>(first_seq_num_, seq_num)) {
133 return;
134 }
philipelaee3e0e2016-11-01 11:45:34 +0100135
136 // If the packet buffer was cleared between a frame was created and returned.
137 if (!first_packet_received_)
138 return;
139
philipelc5fb4682017-08-02 04:28:57 -0700140 // Avoid iterating over the buffer more than once by capping the number of
141 // iterations to the |size_| of the buffer.
142 ++seq_num;
143 size_t diff = ForwardDiff<uint16_t>(first_seq_num_, seq_num);
144 size_t iterations = std::min(diff, size_);
145 for (size_t i = 0; i < iterations; ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100146 size_t index = first_seq_num_ % size_;
philipelc5fb4682017-08-02 04:28:57 -0700147 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
148 if (AheadOf<uint16_t>(seq_num, sequence_buffer_[index].seq_num)) {
149 delete[] data_buffer_[index].dataPtr;
150 data_buffer_[index].dataPtr = nullptr;
151 sequence_buffer_[index].used = false;
152 }
philipelaee3e0e2016-11-01 11:45:34 +0100153 ++first_seq_num_;
philipelc707ab72016-04-01 02:01:54 -0700154 }
philipel2c9f9f22017-06-13 02:47:28 -0700155
philipelc5fb4682017-08-02 04:28:57 -0700156 // If |diff| is larger than |iterations| it means that we don't increment
157 // |first_seq_num_| until we reach |seq_num|, so we set it here.
158 first_seq_num_ = seq_num;
159
160 is_cleared_to_first_seq_num_ = true;
philipel2c9f9f22017-06-13 02:47:28 -0700161 missing_packets_.erase(missing_packets_.begin(),
162 missing_packets_.upper_bound(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700163}
164
philipelaee3e0e2016-11-01 11:45:34 +0100165void PacketBuffer::Clear() {
166 rtc::CritScope lock(&crit_);
167 for (size_t i = 0; i < size_; ++i) {
168 delete[] data_buffer_[i].dataPtr;
169 data_buffer_[i].dataPtr = nullptr;
170 sequence_buffer_[i].used = false;
171 }
172
173 first_packet_received_ = false;
174 is_cleared_to_first_seq_num_ = false;
philipel2c9f9f22017-06-13 02:47:28 -0700175 last_received_packet_ms_.reset();
176 last_received_keyframe_packet_ms_.reset();
177 newest_inserted_seq_num_.reset();
178 missing_packets_.clear();
179}
180
181void PacketBuffer::PaddingReceived(uint16_t seq_num) {
182 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
183 {
184 rtc::CritScope lock(&crit_);
185 UpdateMissingPackets(seq_num);
186 found_frames = FindFrames(static_cast<uint16_t>(seq_num + 1));
187 }
188
189 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
190 received_frame_callback_->OnReceivedFrame(std::move(frame));
philipel3184f8e2017-05-18 08:08:53 -0700191}
192
193rtc::Optional<int64_t> PacketBuffer::LastReceivedPacketMs() const {
194 rtc::CritScope lock(&crit_);
195 return last_received_packet_ms_;
196}
197
198rtc::Optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const {
199 rtc::CritScope lock(&crit_);
200 return last_received_keyframe_packet_ms_;
philipelaee3e0e2016-11-01 11:45:34 +0100201}
202
philipelc707ab72016-04-01 02:01:54 -0700203bool PacketBuffer::ExpandBufferSize() {
philipelaee3e0e2016-11-01 11:45:34 +0100204 if (size_ == max_size_) {
205 LOG(LS_WARNING) << "PacketBuffer is already at max size (" << max_size_
philipelc703dc22017-03-23 06:50:37 -0700206 << "), failed to increase size. Clearing PacketBuffer.";
207 Clear();
philipelc707ab72016-04-01 02:01:54 -0700208 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100209 }
philipelc707ab72016-04-01 02:01:54 -0700210
211 size_t new_size = std::min(max_size_, 2 * size_);
212 std::vector<VCMPacket> new_data_buffer(new_size);
213 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
214 for (size_t i = 0; i < size_; ++i) {
215 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200216 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700217 new_sequence_buffer[index] = sequence_buffer_[i];
218 new_data_buffer[index] = data_buffer_[i];
219 }
220 }
221 size_ = new_size;
222 sequence_buffer_ = std::move(new_sequence_buffer);
223 data_buffer_ = std::move(new_data_buffer);
philipelaee3e0e2016-11-01 11:45:34 +0100224 LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
philipelc707ab72016-04-01 02:01:54 -0700225 return true;
226}
227
philipelaee3e0e2016-11-01 11:45:34 +0100228bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200229 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700230 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200231
philipelc707ab72016-04-01 02:01:54 -0700232 if (!sequence_buffer_[index].used)
233 return false;
philipel2c9f9f22017-06-13 02:47:28 -0700234 if (sequence_buffer_[index].seq_num != seq_num)
235 return false;
philipelf4139332016-04-20 10:26:34 +0200236 if (sequence_buffer_[index].frame_created)
237 return false;
philipel20dce342016-11-28 16:14:57 +0100238 if (sequence_buffer_[index].frame_begin)
philipelc707ab72016-04-01 02:01:54 -0700239 return true;
240 if (!sequence_buffer_[prev_index].used)
241 return false;
philipelea142f82017-01-11 02:01:56 -0800242 if (sequence_buffer_[prev_index].frame_created)
243 return false;
philipelf4139332016-04-20 10:26:34 +0200244 if (sequence_buffer_[prev_index].seq_num !=
philipel2c2f34c2017-01-03 05:55:34 -0800245 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
philipelf4139332016-04-20 10:26:34 +0200246 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100247 }
philipelc707ab72016-04-01 02:01:54 -0700248 if (sequence_buffer_[prev_index].continuous)
249 return true;
250
251 return false;
252}
253
philipelfd5a20f2016-11-15 00:57:57 -0800254std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
255 uint16_t seq_num) {
256 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
philipel53910712017-05-18 02:24:40 -0700257 for (size_t i = 0; i < size_ && PotentialNewFrame(seq_num); ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100258 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700259 sequence_buffer_[index].continuous = true;
260
philipelf4139332016-04-20 10:26:34 +0200261 // If all packets of the frame is continuous, find the first packet of the
262 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700263 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200264 size_t frame_size = 0;
265 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700266 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200267
philipel5ceaaae2016-05-24 10:20:47 +0200268 // Find the start index by searching backward until the packet with
269 // the |frame_begin| flag is set.
270 int start_index = index;
philipel227f8b92017-08-04 06:39:31 -0700271 size_t tested_packets = 0;
philipel8c619242017-02-02 08:51:29 -0800272
273 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264;
philipel2c9f9f22017-06-13 02:47:28 -0700274 bool is_h264_keyframe = false;
philipel8c619242017-02-02 08:51:29 -0800275 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
philipel53910712017-05-18 02:24:40 -0700276
philipel227f8b92017-08-04 06:39:31 -0700277 while (true) {
278 ++tested_packets;
philipel5ceaaae2016-05-24 10:20:47 +0200279 frame_size += data_buffer_[start_index].sizeBytes;
philipelfd5a20f2016-11-15 00:57:57 -0800280 max_nack_count =
281 std::max(max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200282 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200283
philipel8c619242017-02-02 08:51:29 -0800284 if (!is_h264 && sequence_buffer_[start_index].frame_begin)
philipel5ceaaae2016-05-24 10:20:47 +0200285 break;
286
philipel2c9f9f22017-06-13 02:47:28 -0700287 if (is_h264 && !is_h264_keyframe) {
288 const RTPVideoHeaderH264& header =
289 data_buffer_[start_index].video_header.codecHeader.H264;
290 for (size_t i = 0; i < header.nalus_length; ++i) {
291 if (header.nalus[i].type == H264::NaluType::kIdr) {
292 is_h264_keyframe = true;
293 break;
294 }
295 }
296 }
297
philipel227f8b92017-08-04 06:39:31 -0700298 if (tested_packets == size_)
299 break;
300
philipelf4139332016-04-20 10:26:34 +0200301 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipel8c619242017-02-02 08:51:29 -0800302
303 // In the case of H264 we don't have a frame_begin bit (yes,
304 // |frame_begin| might be set to true but that is a lie). So instead
305 // we traverese backwards as long as we have a previous packet and
306 // the timestamp of that packet is the same as this one. This may cause
307 // the PacketBuffer to hand out incomplete frames.
308 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
philipel53910712017-05-18 02:24:40 -0700309 if (is_h264 &&
philipel8c619242017-02-02 08:51:29 -0800310 (!sequence_buffer_[start_index].used ||
311 data_buffer_[start_index].timestamp != frame_timestamp)) {
312 break;
313 }
314
315 --start_seq_num;
philipelc707ab72016-04-01 02:01:54 -0700316 }
317
philipel2c9f9f22017-06-13 02:47:28 -0700318 // If this is H264 but not a keyframe, make sure there are no gaps in the
319 // packet sequence numbers up until this point.
320 if (is_h264 && !is_h264_keyframe &&
321 missing_packets_.upper_bound(start_seq_num) !=
322 missing_packets_.begin()) {
323 uint16_t stop_index = (index + 1) % size_;
324 while (start_index != stop_index) {
325 sequence_buffer_[start_index].frame_created = false;
326 start_index = (start_index + 1) % size_;
327 }
328
329 return found_frames;
330 }
331
332 missing_packets_.erase(missing_packets_.begin(),
333 missing_packets_.upper_bound(seq_num));
334
philipelfd5a20f2016-11-15 00:57:57 -0800335 found_frames.emplace_back(
philipelb4d31082016-07-11 08:46:29 -0700336 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
337 max_nack_count, clock_->TimeInMilliseconds()));
philipelc707ab72016-04-01 02:01:54 -0700338 }
philipelc707ab72016-04-01 02:01:54 -0700339 ++seq_num;
340 }
philipelfd5a20f2016-11-15 00:57:57 -0800341 return found_frames;
philipelc707ab72016-04-01 02:01:54 -0700342}
343
344void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
345 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200346 size_t index = frame->first_seq_num() % size_;
347 size_t end = (frame->last_seq_num() + 1) % size_;
348 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700349 while (index != end) {
philipel1f39ba12016-09-21 11:27:47 +0200350 if (sequence_buffer_[index].seq_num == seq_num) {
351 delete[] data_buffer_[index].dataPtr;
352 data_buffer_[index].dataPtr = nullptr;
philipelc707ab72016-04-01 02:01:54 -0700353 sequence_buffer_[index].used = false;
philipel1f39ba12016-09-21 11:27:47 +0200354 }
philipelf4139332016-04-20 10:26:34 +0200355
philipelc707ab72016-04-01 02:01:54 -0700356 index = (index + 1) % size_;
357 ++seq_num;
358 }
philipelc707ab72016-04-01 02:01:54 -0700359}
360
361bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
362 uint8_t* destination) {
363 rtc::CritScope lock(&crit_);
364
philipelf4139332016-04-20 10:26:34 +0200365 size_t index = frame.first_seq_num() % size_;
366 size_t end = (frame.last_seq_num() + 1) % size_;
367 uint16_t seq_num = frame.first_seq_num();
philipel227f8b92017-08-04 06:39:31 -0700368 uint8_t* destination_end = destination + frame.size();
369
370 do {
philipelc707ab72016-04-01 02:01:54 -0700371 if (!sequence_buffer_[index].used ||
372 sequence_buffer_[index].seq_num != seq_num) {
373 return false;
374 }
375
philipel227f8b92017-08-04 06:39:31 -0700376 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
philipelc18f1d72017-08-02 04:18:02 -0700377 size_t length = data_buffer_[index].sizeBytes;
philipel227f8b92017-08-04 06:39:31 -0700378 if (destination + length > destination_end) {
379 LOG(LS_WARNING) << "Frame (" << frame.picture_id << ":"
380 << static_cast<int>(frame.spatial_layer) << ")"
381 << " bitstream buffer is not large enough.";
382 return false;
383 }
384
385 const uint8_t* source = data_buffer_[index].dataPtr;
philipelc707ab72016-04-01 02:01:54 -0700386 memcpy(destination, source, length);
387 destination += length;
388 index = (index + 1) % size_;
389 ++seq_num;
philipel227f8b92017-08-04 06:39:31 -0700390 } while (index != end);
391
philipelc707ab72016-04-01 02:01:54 -0700392 return true;
393}
394
philipel02447bc2016-05-13 06:01:03 -0700395VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
philipel02447bc2016-05-13 06:01:03 -0700396 size_t index = seq_num % size_;
397 if (!sequence_buffer_[index].used ||
398 seq_num != sequence_buffer_[index].seq_num) {
399 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200400 }
philipel02447bc2016-05-13 06:01:03 -0700401 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200402}
403
philipel17deeb42016-08-11 15:09:26 +0200404int PacketBuffer::AddRef() const {
405 return rtc::AtomicOps::Increment(&ref_count_);
406}
407
408int PacketBuffer::Release() const {
409 int count = rtc::AtomicOps::Decrement(&ref_count_);
410 if (!count) {
411 delete this;
412 }
413 return count;
414}
415
philipel2c9f9f22017-06-13 02:47:28 -0700416void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {
417 if (!newest_inserted_seq_num_)
418 newest_inserted_seq_num_ = rtc::Optional<uint16_t>(seq_num);
419
420 const int kMaxPaddingAge = 1000;
421 if (AheadOf(seq_num, *newest_inserted_seq_num_)) {
422 uint16_t old_seq_num = seq_num - kMaxPaddingAge;
423 auto erase_to = missing_packets_.lower_bound(old_seq_num);
424 missing_packets_.erase(missing_packets_.begin(), erase_to);
425
426 // Guard against inserting a large amount of missing packets if there is a
427 // jump in the sequence number.
428 if (AheadOf(old_seq_num, *newest_inserted_seq_num_))
429 *newest_inserted_seq_num_ = old_seq_num;
430
431 ++*newest_inserted_seq_num_;
432 while (AheadOf(seq_num, *newest_inserted_seq_num_)) {
433 missing_packets_.insert(*newest_inserted_seq_num_);
434 ++*newest_inserted_seq_num_;
435 }
436 } else {
437 missing_packets_.erase(seq_num);
438 }
439}
440
philipelc707ab72016-04-01 02:01:54 -0700441} // namespace video_coding
442} // namespace webrtc