blob: 890604103f04bd60a8487f5a6fe62debfc446c52 [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>
Rasmus Brandt88f080a2017-11-02 14:28:06 +010015#include <sstream>
philipel17deeb42016-08-11 15:09:26 +020016#include <utility>
philipelc707ab72016-04-01 02:01:54 -070017
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "common_video/h264/h264_common.h"
19#include "modules/video_coding/frame_object.h"
20#include "rtc_base/atomicops.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/logging.h"
23#include "system_wrappers/include/clock.h"
Rasmus Brandt88f080a2017-11-02 14:28:06 +010024#include "system_wrappers/include/field_trial.h"
philipelc707ab72016-04-01 02:01:54 -070025
26namespace webrtc {
27namespace video_coding {
28
philipel17deeb42016-08-11 15:09:26 +020029rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create(
30 Clock* clock,
31 size_t start_buffer_size,
32 size_t max_buffer_size,
33 OnReceivedFrameCallback* received_frame_callback) {
34 return rtc::scoped_refptr<PacketBuffer>(new PacketBuffer(
35 clock, start_buffer_size, max_buffer_size, received_frame_callback));
36}
37
philipelb4d31082016-07-11 08:46:29 -070038PacketBuffer::PacketBuffer(Clock* clock,
39 size_t start_buffer_size,
philipelc707ab72016-04-01 02:01:54 -070040 size_t max_buffer_size,
philipel17deeb42016-08-11 15:09:26 +020041 OnReceivedFrameCallback* received_frame_callback)
philipelb4d31082016-07-11 08:46:29 -070042 : clock_(clock),
43 size_(start_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070044 max_size_(max_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070045 first_seq_num_(0),
philipelf4139332016-04-20 10:26:34 +020046 first_packet_received_(false),
philipelaee3e0e2016-11-01 11:45:34 +010047 is_cleared_to_first_seq_num_(false),
philipelc707ab72016-04-01 02:01:54 -070048 data_buffer_(start_buffer_size),
49 sequence_buffer_(start_buffer_size),
Rasmus Brandt88f080a2017-11-02 14:28:06 +010050 received_frame_callback_(received_frame_callback),
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +010051 unique_frames_seen_(0),
Rasmus Brandt88f080a2017-11-02 14:28:06 +010052 sps_pps_idr_is_h264_keyframe_(
53 field_trial::IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe")) {
philipelc707ab72016-04-01 02:01:54 -070054 RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
55 // Buffer size must always be a power of 2.
56 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
57 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
58}
59
philipelaee3e0e2016-11-01 11:45:34 +010060PacketBuffer::~PacketBuffer() {
61 Clear();
62}
philipel17deeb42016-08-11 15:09:26 +020063
philipel759e0b72016-11-30 01:32:05 -080064bool PacketBuffer::InsertPacket(VCMPacket* packet) {
philipelfd5a20f2016-11-15 00:57:57 -080065 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
66 {
67 rtc::CritScope lock(&crit_);
philipel3184f8e2017-05-18 08:08:53 -070068
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +010069 OnTimestampReceived(packet->timestamp);
70
philipel759e0b72016-11-30 01:32:05 -080071 uint16_t seq_num = packet->seqNum;
philipelfd5a20f2016-11-15 00:57:57 -080072 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -070073
philipelfd5a20f2016-11-15 00:57:57 -080074 if (!first_packet_received_) {
75 first_seq_num_ = seq_num;
philipelfd5a20f2016-11-15 00:57:57 -080076 first_packet_received_ = true;
77 } else if (AheadOf(first_seq_num_, seq_num)) {
78 // If we have explicitly cleared past this packet then it's old,
79 // don't insert it.
philipel759e0b72016-11-30 01:32:05 -080080 if (is_cleared_to_first_seq_num_) {
81 delete[] packet->dataPtr;
82 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -080083 return false;
philipel759e0b72016-11-30 01:32:05 -080084 }
philipelaee3e0e2016-11-01 11:45:34 +010085
philipelfd5a20f2016-11-15 00:57:57 -080086 first_seq_num_ = seq_num;
philipelc707ab72016-04-01 02:01:54 -070087 }
philipelc707ab72016-04-01 02:01:54 -070088
philipelfd5a20f2016-11-15 00:57:57 -080089 if (sequence_buffer_[index].used) {
philipel759e0b72016-11-30 01:32:05 -080090 // Duplicate packet, just delete the payload.
91 if (data_buffer_[index].seqNum == packet->seqNum) {
92 delete[] packet->dataPtr;
93 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -080094 return true;
philipel759e0b72016-11-30 01:32:05 -080095 }
philipelfd5a20f2016-11-15 00:57:57 -080096
97 // The packet buffer is full, try to expand the buffer.
98 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
99 }
100 index = seq_num % size_;
101
102 // Packet buffer is still full.
philipel759e0b72016-11-30 01:32:05 -0800103 if (sequence_buffer_[index].used) {
104 delete[] packet->dataPtr;
105 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800106 return false;
philipel759e0b72016-11-30 01:32:05 -0800107 }
philipelfd5a20f2016-11-15 00:57:57 -0800108 }
109
johan0d1b2b62017-01-10 04:21:35 -0800110 sequence_buffer_[index].frame_begin = packet->is_first_packet_in_frame;
philipel759e0b72016-11-30 01:32:05 -0800111 sequence_buffer_[index].frame_end = packet->markerBit;
112 sequence_buffer_[index].seq_num = packet->seqNum;
philipelfd5a20f2016-11-15 00:57:57 -0800113 sequence_buffer_[index].continuous = false;
114 sequence_buffer_[index].frame_created = false;
115 sequence_buffer_[index].used = true;
philipel759e0b72016-11-30 01:32:05 -0800116 data_buffer_[index] = *packet;
117 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800118
philipel2c9f9f22017-06-13 02:47:28 -0700119 UpdateMissingPackets(packet->seqNum);
120
philipel3184f8e2017-05-18 08:08:53 -0700121 int64_t now_ms = clock_->TimeInMilliseconds();
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100122 last_received_packet_ms_ = now_ms;
philipel3184f8e2017-05-18 08:08:53 -0700123 if (packet->frameType == kVideoFrameKey)
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100124 last_received_keyframe_packet_ms_ = now_ms;
philipel3184f8e2017-05-18 08:08:53 -0700125
philipelfd5a20f2016-11-15 00:57:57 -0800126 found_frames = FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -0700127 }
128
philipelfd5a20f2016-11-15 00:57:57 -0800129 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
130 received_frame_callback_->OnReceivedFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700131
philipelc707ab72016-04-01 02:01:54 -0700132 return true;
133}
134
135void PacketBuffer::ClearTo(uint16_t seq_num) {
136 rtc::CritScope lock(&crit_);
philipelc5fb4682017-08-02 04:28:57 -0700137 // We have already cleared past this sequence number, no need to do anything.
138 if (is_cleared_to_first_seq_num_ &&
139 AheadOf<uint16_t>(first_seq_num_, seq_num)) {
140 return;
141 }
philipelaee3e0e2016-11-01 11:45:34 +0100142
143 // If the packet buffer was cleared between a frame was created and returned.
144 if (!first_packet_received_)
145 return;
146
philipelc5fb4682017-08-02 04:28:57 -0700147 // Avoid iterating over the buffer more than once by capping the number of
148 // iterations to the |size_| of the buffer.
149 ++seq_num;
150 size_t diff = ForwardDiff<uint16_t>(first_seq_num_, seq_num);
151 size_t iterations = std::min(diff, size_);
152 for (size_t i = 0; i < iterations; ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100153 size_t index = first_seq_num_ % size_;
philipelc5fb4682017-08-02 04:28:57 -0700154 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
155 if (AheadOf<uint16_t>(seq_num, sequence_buffer_[index].seq_num)) {
156 delete[] data_buffer_[index].dataPtr;
157 data_buffer_[index].dataPtr = nullptr;
158 sequence_buffer_[index].used = false;
159 }
philipelaee3e0e2016-11-01 11:45:34 +0100160 ++first_seq_num_;
philipelc707ab72016-04-01 02:01:54 -0700161 }
philipel2c9f9f22017-06-13 02:47:28 -0700162
philipelc5fb4682017-08-02 04:28:57 -0700163 // If |diff| is larger than |iterations| it means that we don't increment
164 // |first_seq_num_| until we reach |seq_num|, so we set it here.
165 first_seq_num_ = seq_num;
166
167 is_cleared_to_first_seq_num_ = true;
philipelbc5a4082017-12-06 10:41:08 +0100168 auto clear_to_it = missing_packets_.upper_bound(seq_num);
169 if (clear_to_it != missing_packets_.begin()) {
170 --clear_to_it;
171 missing_packets_.erase(missing_packets_.begin(), clear_to_it);
172 }
philipelc707ab72016-04-01 02:01:54 -0700173}
174
philipelaee3e0e2016-11-01 11:45:34 +0100175void PacketBuffer::Clear() {
176 rtc::CritScope lock(&crit_);
177 for (size_t i = 0; i < size_; ++i) {
178 delete[] data_buffer_[i].dataPtr;
179 data_buffer_[i].dataPtr = nullptr;
180 sequence_buffer_[i].used = false;
181 }
182
183 first_packet_received_ = false;
184 is_cleared_to_first_seq_num_ = false;
philipel2c9f9f22017-06-13 02:47:28 -0700185 last_received_packet_ms_.reset();
186 last_received_keyframe_packet_ms_.reset();
187 newest_inserted_seq_num_.reset();
188 missing_packets_.clear();
189}
190
191void PacketBuffer::PaddingReceived(uint16_t seq_num) {
192 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
193 {
194 rtc::CritScope lock(&crit_);
195 UpdateMissingPackets(seq_num);
196 found_frames = FindFrames(static_cast<uint16_t>(seq_num + 1));
197 }
198
199 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
200 received_frame_callback_->OnReceivedFrame(std::move(frame));
philipel3184f8e2017-05-18 08:08:53 -0700201}
202
203rtc::Optional<int64_t> PacketBuffer::LastReceivedPacketMs() const {
204 rtc::CritScope lock(&crit_);
205 return last_received_packet_ms_;
206}
207
208rtc::Optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const {
209 rtc::CritScope lock(&crit_);
210 return last_received_keyframe_packet_ms_;
philipelaee3e0e2016-11-01 11:45:34 +0100211}
212
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +0100213int PacketBuffer::GetUniqueFramesSeen() const {
214 rtc::CritScope lock(&crit_);
215 return unique_frames_seen_;
216}
217
philipelc707ab72016-04-01 02:01:54 -0700218bool PacketBuffer::ExpandBufferSize() {
philipelaee3e0e2016-11-01 11:45:34 +0100219 if (size_ == max_size_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100220 RTC_LOG(LS_WARNING) << "PacketBuffer is already at max size (" << max_size_
221 << "), failed to increase size. Clearing PacketBuffer.";
philipelc703dc22017-03-23 06:50:37 -0700222 Clear();
philipelc707ab72016-04-01 02:01:54 -0700223 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100224 }
philipelc707ab72016-04-01 02:01:54 -0700225
226 size_t new_size = std::min(max_size_, 2 * size_);
227 std::vector<VCMPacket> new_data_buffer(new_size);
228 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
229 for (size_t i = 0; i < size_; ++i) {
230 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200231 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700232 new_sequence_buffer[index] = sequence_buffer_[i];
233 new_data_buffer[index] = data_buffer_[i];
234 }
235 }
236 size_ = new_size;
237 sequence_buffer_ = std::move(new_sequence_buffer);
238 data_buffer_ = std::move(new_data_buffer);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100239 RTC_LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
philipelc707ab72016-04-01 02:01:54 -0700240 return true;
241}
242
philipelaee3e0e2016-11-01 11:45:34 +0100243bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200244 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700245 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200246
philipelc707ab72016-04-01 02:01:54 -0700247 if (!sequence_buffer_[index].used)
248 return false;
philipel2c9f9f22017-06-13 02:47:28 -0700249 if (sequence_buffer_[index].seq_num != seq_num)
250 return false;
philipelf4139332016-04-20 10:26:34 +0200251 if (sequence_buffer_[index].frame_created)
252 return false;
philipel20dce342016-11-28 16:14:57 +0100253 if (sequence_buffer_[index].frame_begin)
philipelc707ab72016-04-01 02:01:54 -0700254 return true;
255 if (!sequence_buffer_[prev_index].used)
256 return false;
philipelea142f82017-01-11 02:01:56 -0800257 if (sequence_buffer_[prev_index].frame_created)
258 return false;
philipelf4139332016-04-20 10:26:34 +0200259 if (sequence_buffer_[prev_index].seq_num !=
philipel2c2f34c2017-01-03 05:55:34 -0800260 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
philipelf4139332016-04-20 10:26:34 +0200261 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100262 }
philipelc707ab72016-04-01 02:01:54 -0700263 if (sequence_buffer_[prev_index].continuous)
264 return true;
265
266 return false;
267}
268
philipelfd5a20f2016-11-15 00:57:57 -0800269std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
270 uint16_t seq_num) {
271 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
philipel53910712017-05-18 02:24:40 -0700272 for (size_t i = 0; i < size_ && PotentialNewFrame(seq_num); ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100273 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700274 sequence_buffer_[index].continuous = true;
275
philipelf4139332016-04-20 10:26:34 +0200276 // If all packets of the frame is continuous, find the first packet of the
277 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700278 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200279 size_t frame_size = 0;
280 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700281 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200282
philipel5ceaaae2016-05-24 10:20:47 +0200283 // Find the start index by searching backward until the packet with
284 // the |frame_begin| flag is set.
285 int start_index = index;
philipel227f8b92017-08-04 06:39:31 -0700286 size_t tested_packets = 0;
philipel8c619242017-02-02 08:51:29 -0800287 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
philipel53910712017-05-18 02:24:40 -0700288
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100289 // Identify H.264 keyframes by means of SPS, PPS, and IDR.
290 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264;
291 bool has_h264_sps = false;
292 bool has_h264_pps = false;
293 bool has_h264_idr = false;
294 bool is_h264_keyframe = false;
295
philipel227f8b92017-08-04 06:39:31 -0700296 while (true) {
297 ++tested_packets;
philipel5ceaaae2016-05-24 10:20:47 +0200298 frame_size += data_buffer_[start_index].sizeBytes;
philipelfd5a20f2016-11-15 00:57:57 -0800299 max_nack_count =
300 std::max(max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200301 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200302
philipel8c619242017-02-02 08:51:29 -0800303 if (!is_h264 && sequence_buffer_[start_index].frame_begin)
philipel5ceaaae2016-05-24 10:20:47 +0200304 break;
305
philipel2c9f9f22017-06-13 02:47:28 -0700306 if (is_h264 && !is_h264_keyframe) {
307 const RTPVideoHeaderH264& header =
308 data_buffer_[start_index].video_header.codecHeader.H264;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100309 for (size_t j = 0; j < header.nalus_length; ++j) {
310 if (header.nalus[j].type == H264::NaluType::kSps) {
311 has_h264_sps = true;
312 } else if (header.nalus[j].type == H264::NaluType::kPps) {
313 has_h264_pps = true;
314 } else if (header.nalus[j].type == H264::NaluType::kIdr) {
315 has_h264_idr = true;
philipel2c9f9f22017-06-13 02:47:28 -0700316 }
317 }
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100318 if ((sps_pps_idr_is_h264_keyframe_ && has_h264_idr && has_h264_sps &&
319 has_h264_pps) ||
320 (!sps_pps_idr_is_h264_keyframe_ && has_h264_idr)) {
321 is_h264_keyframe = true;
322 }
philipel2c9f9f22017-06-13 02:47:28 -0700323 }
324
philipel227f8b92017-08-04 06:39:31 -0700325 if (tested_packets == size_)
326 break;
327
philipelf4139332016-04-20 10:26:34 +0200328 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipel8c619242017-02-02 08:51:29 -0800329
330 // In the case of H264 we don't have a frame_begin bit (yes,
331 // |frame_begin| might be set to true but that is a lie). So instead
332 // we traverese backwards as long as we have a previous packet and
333 // the timestamp of that packet is the same as this one. This may cause
334 // the PacketBuffer to hand out incomplete frames.
335 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
philipel53910712017-05-18 02:24:40 -0700336 if (is_h264 &&
philipel8c619242017-02-02 08:51:29 -0800337 (!sequence_buffer_[start_index].used ||
338 data_buffer_[start_index].timestamp != frame_timestamp)) {
339 break;
340 }
341
342 --start_seq_num;
philipelc707ab72016-04-01 02:01:54 -0700343 }
344
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100345 if (is_h264) {
346 // Warn if this is an unsafe frame.
347 if (has_h264_idr && (!has_h264_sps || !has_h264_pps)) {
348 std::stringstream ss;
349 ss << "Received H.264-IDR frame "
350 << "(SPS: " << has_h264_sps << ", PPS: " << has_h264_pps << "). ";
351 if (sps_pps_idr_is_h264_keyframe_) {
352 ss << "Treating as delta frame since "
353 "WebRTC-SpsPpsIdrIsH264Keyframe is enabled.";
354 } else {
355 ss << "Treating as key frame since "
356 "WebRTC-SpsPpsIdrIsH264Keyframe is disabled.";
357 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100358 RTC_LOG(LS_WARNING) << ss.str();
philipel2c9f9f22017-06-13 02:47:28 -0700359 }
360
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100361 // Now that we have decided whether to treat this frame as a key frame
362 // or delta frame in the frame buffer, we update the field that
363 // determines if the RtpFrameObject is a key frame or delta frame.
364 const size_t first_packet_index = start_seq_num % size_;
365 RTC_CHECK_LT(first_packet_index, size_);
366 if (is_h264_keyframe) {
367 data_buffer_[first_packet_index].frameType = kVideoFrameKey;
368 } else {
369 data_buffer_[first_packet_index].frameType = kVideoFrameDelta;
370 }
371
372 // If this is not a keyframe, make sure there are no gaps in the
373 // packet sequence numbers up until this point.
374 if (!is_h264_keyframe && missing_packets_.upper_bound(start_seq_num) !=
375 missing_packets_.begin()) {
376 uint16_t stop_index = (index + 1) % size_;
377 while (start_index != stop_index) {
378 sequence_buffer_[start_index].frame_created = false;
379 start_index = (start_index + 1) % size_;
380 }
381
382 return found_frames;
383 }
philipel2c9f9f22017-06-13 02:47:28 -0700384 }
385
386 missing_packets_.erase(missing_packets_.begin(),
387 missing_packets_.upper_bound(seq_num));
388
philipelfd5a20f2016-11-15 00:57:57 -0800389 found_frames.emplace_back(
philipelb4d31082016-07-11 08:46:29 -0700390 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
391 max_nack_count, clock_->TimeInMilliseconds()));
philipelc707ab72016-04-01 02:01:54 -0700392 }
philipelc707ab72016-04-01 02:01:54 -0700393 ++seq_num;
394 }
philipelfd5a20f2016-11-15 00:57:57 -0800395 return found_frames;
philipelc707ab72016-04-01 02:01:54 -0700396}
397
398void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
399 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200400 size_t index = frame->first_seq_num() % size_;
401 size_t end = (frame->last_seq_num() + 1) % size_;
402 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700403 while (index != end) {
philipel1f39ba12016-09-21 11:27:47 +0200404 if (sequence_buffer_[index].seq_num == seq_num) {
405 delete[] data_buffer_[index].dataPtr;
406 data_buffer_[index].dataPtr = nullptr;
philipelc707ab72016-04-01 02:01:54 -0700407 sequence_buffer_[index].used = false;
philipel1f39ba12016-09-21 11:27:47 +0200408 }
philipelf4139332016-04-20 10:26:34 +0200409
philipelc707ab72016-04-01 02:01:54 -0700410 index = (index + 1) % size_;
411 ++seq_num;
412 }
philipelc707ab72016-04-01 02:01:54 -0700413}
414
415bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
416 uint8_t* destination) {
417 rtc::CritScope lock(&crit_);
418
philipelf4139332016-04-20 10:26:34 +0200419 size_t index = frame.first_seq_num() % size_;
420 size_t end = (frame.last_seq_num() + 1) % size_;
421 uint16_t seq_num = frame.first_seq_num();
philipel227f8b92017-08-04 06:39:31 -0700422 uint8_t* destination_end = destination + frame.size();
423
424 do {
philipelc707ab72016-04-01 02:01:54 -0700425 if (!sequence_buffer_[index].used ||
426 sequence_buffer_[index].seq_num != seq_num) {
427 return false;
428 }
429
philipel227f8b92017-08-04 06:39:31 -0700430 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
philipelc18f1d72017-08-02 04:18:02 -0700431 size_t length = data_buffer_[index].sizeBytes;
philipel227f8b92017-08-04 06:39:31 -0700432 if (destination + length > destination_end) {
philipel0fa82a62018-03-19 15:34:53 +0100433 RTC_LOG(LS_WARNING) << "Frame (" << frame.id.picture_id << ":"
434 << static_cast<int>(frame.id.spatial_layer) << ")"
Mirko Bonadei675513b2017-11-09 11:09:25 +0100435 << " bitstream buffer is not large enough.";
philipel227f8b92017-08-04 06:39:31 -0700436 return false;
437 }
438
439 const uint8_t* source = data_buffer_[index].dataPtr;
philipelc707ab72016-04-01 02:01:54 -0700440 memcpy(destination, source, length);
441 destination += length;
442 index = (index + 1) % size_;
443 ++seq_num;
philipel227f8b92017-08-04 06:39:31 -0700444 } while (index != end);
445
philipelc707ab72016-04-01 02:01:54 -0700446 return true;
447}
448
philipel02447bc2016-05-13 06:01:03 -0700449VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
philipel02447bc2016-05-13 06:01:03 -0700450 size_t index = seq_num % size_;
451 if (!sequence_buffer_[index].used ||
452 seq_num != sequence_buffer_[index].seq_num) {
453 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200454 }
philipel02447bc2016-05-13 06:01:03 -0700455 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200456}
457
philipel17deeb42016-08-11 15:09:26 +0200458int PacketBuffer::AddRef() const {
459 return rtc::AtomicOps::Increment(&ref_count_);
460}
461
462int PacketBuffer::Release() const {
463 int count = rtc::AtomicOps::Decrement(&ref_count_);
464 if (!count) {
465 delete this;
466 }
467 return count;
468}
469
philipel2c9f9f22017-06-13 02:47:28 -0700470void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {
471 if (!newest_inserted_seq_num_)
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100472 newest_inserted_seq_num_ = seq_num;
philipel2c9f9f22017-06-13 02:47:28 -0700473
474 const int kMaxPaddingAge = 1000;
475 if (AheadOf(seq_num, *newest_inserted_seq_num_)) {
476 uint16_t old_seq_num = seq_num - kMaxPaddingAge;
477 auto erase_to = missing_packets_.lower_bound(old_seq_num);
478 missing_packets_.erase(missing_packets_.begin(), erase_to);
479
480 // Guard against inserting a large amount of missing packets if there is a
481 // jump in the sequence number.
482 if (AheadOf(old_seq_num, *newest_inserted_seq_num_))
483 *newest_inserted_seq_num_ = old_seq_num;
484
485 ++*newest_inserted_seq_num_;
486 while (AheadOf(seq_num, *newest_inserted_seq_num_)) {
487 missing_packets_.insert(*newest_inserted_seq_num_);
488 ++*newest_inserted_seq_num_;
489 }
490 } else {
491 missing_packets_.erase(seq_num);
492 }
493}
494
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +0100495void PacketBuffer::OnTimestampReceived(uint32_t rtp_timestamp) {
496 const size_t kMaxTimestampsHistory = 1000;
497 if (rtp_timestamps_history_set_.insert(rtp_timestamp).second) {
498 rtp_timestamps_history_queue_.push(rtp_timestamp);
499 ++unique_frames_seen_;
500 if (rtp_timestamps_history_set_.size() > kMaxTimestampsHistory) {
501 uint32_t discarded_timestamp = rtp_timestamps_history_queue_.front();
502 rtp_timestamps_history_set_.erase(discarded_timestamp);
503 rtp_timestamps_history_queue_.pop();
504 }
505 }
506}
507
philipelc707ab72016-04-01 02:01:54 -0700508} // namespace video_coding
509} // namespace webrtc