blob: 8b6de047ca5bb6aa3e7f542dacdd8f48cf6c5559 [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
11#include "webrtc/modules/video_coding/packet_buffer.h"
12
13#include <algorithm>
14#include <limits>
philipel17deeb42016-08-11 15:09:26 +020015#include <utility>
philipelc707ab72016-04-01 02:01:54 -070016
philipel2c9f9f22017-06-13 02:47:28 -070017#include "webrtc/common_video/h264/h264_common.h"
philipelc707ab72016-04-01 02:01:54 -070018#include "webrtc/modules/video_coding/frame_object.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020019#include "webrtc/rtc_base/atomicops.h"
20#include "webrtc/rtc_base/checks.h"
21#include "webrtc/rtc_base/logging.h"
philipelb4d31082016-07-11 08:46:29 -070022#include "webrtc/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_);
philipelaee3e0e2016-11-01 11:45:34 +0100130
131 // If the packet buffer was cleared between a frame was created and returned.
132 if (!first_packet_received_)
133 return;
134
135 is_cleared_to_first_seq_num_ = true;
136 while (AheadOrAt<uint16_t>(seq_num, first_seq_num_)) {
137 size_t index = first_seq_num_ % size_;
philipel1f39ba12016-09-21 11:27:47 +0200138 delete[] data_buffer_[index].dataPtr;
139 data_buffer_[index].dataPtr = nullptr;
philipelc707ab72016-04-01 02:01:54 -0700140 sequence_buffer_[index].used = false;
philipelaee3e0e2016-11-01 11:45:34 +0100141 ++first_seq_num_;
philipelc707ab72016-04-01 02:01:54 -0700142 }
philipel2c9f9f22017-06-13 02:47:28 -0700143
144 missing_packets_.erase(missing_packets_.begin(),
145 missing_packets_.upper_bound(seq_num));
philipelc707ab72016-04-01 02:01:54 -0700146}
147
philipelaee3e0e2016-11-01 11:45:34 +0100148void PacketBuffer::Clear() {
149 rtc::CritScope lock(&crit_);
150 for (size_t i = 0; i < size_; ++i) {
151 delete[] data_buffer_[i].dataPtr;
152 data_buffer_[i].dataPtr = nullptr;
153 sequence_buffer_[i].used = false;
154 }
155
156 first_packet_received_ = false;
157 is_cleared_to_first_seq_num_ = false;
philipel2c9f9f22017-06-13 02:47:28 -0700158 last_received_packet_ms_.reset();
159 last_received_keyframe_packet_ms_.reset();
160 newest_inserted_seq_num_.reset();
161 missing_packets_.clear();
162}
163
164void PacketBuffer::PaddingReceived(uint16_t seq_num) {
165 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
166 {
167 rtc::CritScope lock(&crit_);
168 UpdateMissingPackets(seq_num);
169 found_frames = FindFrames(static_cast<uint16_t>(seq_num + 1));
170 }
171
172 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
173 received_frame_callback_->OnReceivedFrame(std::move(frame));
philipel3184f8e2017-05-18 08:08:53 -0700174}
175
176rtc::Optional<int64_t> PacketBuffer::LastReceivedPacketMs() const {
177 rtc::CritScope lock(&crit_);
178 return last_received_packet_ms_;
179}
180
181rtc::Optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const {
182 rtc::CritScope lock(&crit_);
183 return last_received_keyframe_packet_ms_;
philipelaee3e0e2016-11-01 11:45:34 +0100184}
185
philipelc707ab72016-04-01 02:01:54 -0700186bool PacketBuffer::ExpandBufferSize() {
philipelaee3e0e2016-11-01 11:45:34 +0100187 if (size_ == max_size_) {
188 LOG(LS_WARNING) << "PacketBuffer is already at max size (" << max_size_
philipelc703dc22017-03-23 06:50:37 -0700189 << "), failed to increase size. Clearing PacketBuffer.";
190 Clear();
philipelc707ab72016-04-01 02:01:54 -0700191 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100192 }
philipelc707ab72016-04-01 02:01:54 -0700193
194 size_t new_size = std::min(max_size_, 2 * size_);
195 std::vector<VCMPacket> new_data_buffer(new_size);
196 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
197 for (size_t i = 0; i < size_; ++i) {
198 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200199 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700200 new_sequence_buffer[index] = sequence_buffer_[i];
201 new_data_buffer[index] = data_buffer_[i];
202 }
203 }
204 size_ = new_size;
205 sequence_buffer_ = std::move(new_sequence_buffer);
206 data_buffer_ = std::move(new_data_buffer);
philipelaee3e0e2016-11-01 11:45:34 +0100207 LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
philipelc707ab72016-04-01 02:01:54 -0700208 return true;
209}
210
philipelaee3e0e2016-11-01 11:45:34 +0100211bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200212 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700213 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200214
philipelc707ab72016-04-01 02:01:54 -0700215 if (!sequence_buffer_[index].used)
216 return false;
philipel2c9f9f22017-06-13 02:47:28 -0700217 if (sequence_buffer_[index].seq_num != seq_num)
218 return false;
philipelf4139332016-04-20 10:26:34 +0200219 if (sequence_buffer_[index].frame_created)
220 return false;
philipel20dce342016-11-28 16:14:57 +0100221 if (sequence_buffer_[index].frame_begin)
philipelc707ab72016-04-01 02:01:54 -0700222 return true;
223 if (!sequence_buffer_[prev_index].used)
224 return false;
philipelea142f82017-01-11 02:01:56 -0800225 if (sequence_buffer_[prev_index].frame_created)
226 return false;
philipelf4139332016-04-20 10:26:34 +0200227 if (sequence_buffer_[prev_index].seq_num !=
philipel2c2f34c2017-01-03 05:55:34 -0800228 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
philipelf4139332016-04-20 10:26:34 +0200229 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100230 }
philipelc707ab72016-04-01 02:01:54 -0700231 if (sequence_buffer_[prev_index].continuous)
232 return true;
233
234 return false;
235}
236
philipelfd5a20f2016-11-15 00:57:57 -0800237std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
238 uint16_t seq_num) {
239 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
philipel53910712017-05-18 02:24:40 -0700240 for (size_t i = 0; i < size_ && PotentialNewFrame(seq_num); ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100241 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700242 sequence_buffer_[index].continuous = true;
243
philipelf4139332016-04-20 10:26:34 +0200244 // If all packets of the frame is continuous, find the first packet of the
245 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700246 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200247 size_t frame_size = 0;
248 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700249 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200250
philipel5ceaaae2016-05-24 10:20:47 +0200251 // Find the start index by searching backward until the packet with
252 // the |frame_begin| flag is set.
253 int start_index = index;
philipel8c619242017-02-02 08:51:29 -0800254
255 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264;
philipel2c9f9f22017-06-13 02:47:28 -0700256 bool is_h264_keyframe = false;
philipel8c619242017-02-02 08:51:29 -0800257 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
philipel53910712017-05-18 02:24:40 -0700258
259 // Since packet at |data_buffer_[index]| is already part of the frame
260 // we will have at most |size_ - 1| packets left to check.
261 for (size_t j = 0; j < size_ - 1; ++j) {
philipel5ceaaae2016-05-24 10:20:47 +0200262 frame_size += data_buffer_[start_index].sizeBytes;
philipelfd5a20f2016-11-15 00:57:57 -0800263 max_nack_count =
264 std::max(max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200265 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200266
philipel8c619242017-02-02 08:51:29 -0800267 if (!is_h264 && sequence_buffer_[start_index].frame_begin)
philipel5ceaaae2016-05-24 10:20:47 +0200268 break;
269
philipel2c9f9f22017-06-13 02:47:28 -0700270 if (is_h264 && !is_h264_keyframe) {
271 const RTPVideoHeaderH264& header =
272 data_buffer_[start_index].video_header.codecHeader.H264;
273 for (size_t i = 0; i < header.nalus_length; ++i) {
274 if (header.nalus[i].type == H264::NaluType::kIdr) {
275 is_h264_keyframe = true;
276 break;
277 }
278 }
279 }
280
philipelf4139332016-04-20 10:26:34 +0200281 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipel8c619242017-02-02 08:51:29 -0800282
283 // In the case of H264 we don't have a frame_begin bit (yes,
284 // |frame_begin| might be set to true but that is a lie). So instead
285 // we traverese backwards as long as we have a previous packet and
286 // the timestamp of that packet is the same as this one. This may cause
287 // the PacketBuffer to hand out incomplete frames.
288 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
philipel53910712017-05-18 02:24:40 -0700289 if (is_h264 &&
philipel8c619242017-02-02 08:51:29 -0800290 (!sequence_buffer_[start_index].used ||
291 data_buffer_[start_index].timestamp != frame_timestamp)) {
292 break;
293 }
294
295 --start_seq_num;
philipelc707ab72016-04-01 02:01:54 -0700296 }
297
philipel2c9f9f22017-06-13 02:47:28 -0700298 // If this is H264 but not a keyframe, make sure there are no gaps in the
299 // packet sequence numbers up until this point.
300 if (is_h264 && !is_h264_keyframe &&
301 missing_packets_.upper_bound(start_seq_num) !=
302 missing_packets_.begin()) {
303 uint16_t stop_index = (index + 1) % size_;
304 while (start_index != stop_index) {
305 sequence_buffer_[start_index].frame_created = false;
306 start_index = (start_index + 1) % size_;
307 }
308
309 return found_frames;
310 }
311
312 missing_packets_.erase(missing_packets_.begin(),
313 missing_packets_.upper_bound(seq_num));
314
philipelfd5a20f2016-11-15 00:57:57 -0800315 found_frames.emplace_back(
philipelb4d31082016-07-11 08:46:29 -0700316 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
317 max_nack_count, clock_->TimeInMilliseconds()));
philipelc707ab72016-04-01 02:01:54 -0700318 }
philipelc707ab72016-04-01 02:01:54 -0700319 ++seq_num;
320 }
philipelfd5a20f2016-11-15 00:57:57 -0800321 return found_frames;
philipelc707ab72016-04-01 02:01:54 -0700322}
323
324void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
325 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200326 size_t index = frame->first_seq_num() % size_;
327 size_t end = (frame->last_seq_num() + 1) % size_;
328 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700329 while (index != end) {
philipel1f39ba12016-09-21 11:27:47 +0200330 if (sequence_buffer_[index].seq_num == seq_num) {
331 delete[] data_buffer_[index].dataPtr;
332 data_buffer_[index].dataPtr = nullptr;
philipelc707ab72016-04-01 02:01:54 -0700333 sequence_buffer_[index].used = false;
philipel1f39ba12016-09-21 11:27:47 +0200334 }
philipelf4139332016-04-20 10:26:34 +0200335
philipelc707ab72016-04-01 02:01:54 -0700336 index = (index + 1) % size_;
337 ++seq_num;
338 }
philipelc707ab72016-04-01 02:01:54 -0700339}
340
341bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
342 uint8_t* destination) {
343 rtc::CritScope lock(&crit_);
344
philipelf4139332016-04-20 10:26:34 +0200345 size_t index = frame.first_seq_num() % size_;
346 size_t end = (frame.last_seq_num() + 1) % size_;
347 uint16_t seq_num = frame.first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700348 while (index != end) {
349 if (!sequence_buffer_[index].used ||
350 sequence_buffer_[index].seq_num != seq_num) {
351 return false;
352 }
353
354 const uint8_t* source = data_buffer_[index].dataPtr;
355 size_t length = data_buffer_[index].sizeBytes;
356 memcpy(destination, source, length);
357 destination += length;
358 index = (index + 1) % size_;
359 ++seq_num;
360 }
361 return true;
362}
363
philipel02447bc2016-05-13 06:01:03 -0700364VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
philipel02447bc2016-05-13 06:01:03 -0700365 size_t index = seq_num % size_;
366 if (!sequence_buffer_[index].used ||
367 seq_num != sequence_buffer_[index].seq_num) {
368 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200369 }
philipel02447bc2016-05-13 06:01:03 -0700370 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200371}
372
philipel17deeb42016-08-11 15:09:26 +0200373int PacketBuffer::AddRef() const {
374 return rtc::AtomicOps::Increment(&ref_count_);
375}
376
377int PacketBuffer::Release() const {
378 int count = rtc::AtomicOps::Decrement(&ref_count_);
379 if (!count) {
380 delete this;
381 }
382 return count;
383}
384
philipel2c9f9f22017-06-13 02:47:28 -0700385void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {
386 if (!newest_inserted_seq_num_)
387 newest_inserted_seq_num_ = rtc::Optional<uint16_t>(seq_num);
388
389 const int kMaxPaddingAge = 1000;
390 if (AheadOf(seq_num, *newest_inserted_seq_num_)) {
391 uint16_t old_seq_num = seq_num - kMaxPaddingAge;
392 auto erase_to = missing_packets_.lower_bound(old_seq_num);
393 missing_packets_.erase(missing_packets_.begin(), erase_to);
394
395 // Guard against inserting a large amount of missing packets if there is a
396 // jump in the sequence number.
397 if (AheadOf(old_seq_num, *newest_inserted_seq_num_))
398 *newest_inserted_seq_num_ = old_seq_num;
399
400 ++*newest_inserted_seq_num_;
401 while (AheadOf(seq_num, *newest_inserted_seq_num_)) {
402 missing_packets_.insert(*newest_inserted_seq_num_);
403 ++*newest_inserted_seq_num_;
404 }
405 } else {
406 missing_packets_.erase(seq_num);
407 }
408}
409
philipelc707ab72016-04-01 02:01:54 -0700410} // namespace video_coding
411} // namespace webrtc