blob: 715a173e9c3b926952df55559f1094be68fd58c4 [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;
philipelee13e892017-08-02 02:07:48 -0700254 size_t tested_packets = 0;
philipel8c619242017-02-02 08:51:29 -0800255
256 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264;
philipel2c9f9f22017-06-13 02:47:28 -0700257 bool is_h264_keyframe = false;
philipel8c619242017-02-02 08:51:29 -0800258 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
philipel53910712017-05-18 02:24:40 -0700259
philipelee13e892017-08-02 02:07:48 -0700260 while (true) {
261 ++tested_packets;
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
philipelee13e892017-08-02 02:07:48 -0700281 if (tested_packets == size_)
282 break;
283
philipelf4139332016-04-20 10:26:34 +0200284 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipel8c619242017-02-02 08:51:29 -0800285
286 // In the case of H264 we don't have a frame_begin bit (yes,
287 // |frame_begin| might be set to true but that is a lie). So instead
288 // we traverese backwards as long as we have a previous packet and
289 // the timestamp of that packet is the same as this one. This may cause
290 // the PacketBuffer to hand out incomplete frames.
291 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
philipel53910712017-05-18 02:24:40 -0700292 if (is_h264 &&
philipel8c619242017-02-02 08:51:29 -0800293 (!sequence_buffer_[start_index].used ||
294 data_buffer_[start_index].timestamp != frame_timestamp)) {
295 break;
296 }
297
298 --start_seq_num;
philipelc707ab72016-04-01 02:01:54 -0700299 }
300
philipel2c9f9f22017-06-13 02:47:28 -0700301 // If this is H264 but not a keyframe, make sure there are no gaps in the
302 // packet sequence numbers up until this point.
303 if (is_h264 && !is_h264_keyframe &&
304 missing_packets_.upper_bound(start_seq_num) !=
305 missing_packets_.begin()) {
306 uint16_t stop_index = (index + 1) % size_;
307 while (start_index != stop_index) {
308 sequence_buffer_[start_index].frame_created = false;
309 start_index = (start_index + 1) % size_;
310 }
311
312 return found_frames;
313 }
314
315 missing_packets_.erase(missing_packets_.begin(),
316 missing_packets_.upper_bound(seq_num));
317
philipelfd5a20f2016-11-15 00:57:57 -0800318 found_frames.emplace_back(
philipelb4d31082016-07-11 08:46:29 -0700319 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
320 max_nack_count, clock_->TimeInMilliseconds()));
philipelc707ab72016-04-01 02:01:54 -0700321 }
philipelc707ab72016-04-01 02:01:54 -0700322 ++seq_num;
323 }
philipelfd5a20f2016-11-15 00:57:57 -0800324 return found_frames;
philipelc707ab72016-04-01 02:01:54 -0700325}
326
327void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
328 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200329 size_t index = frame->first_seq_num() % size_;
330 size_t end = (frame->last_seq_num() + 1) % size_;
331 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700332 while (index != end) {
philipel1f39ba12016-09-21 11:27:47 +0200333 if (sequence_buffer_[index].seq_num == seq_num) {
334 delete[] data_buffer_[index].dataPtr;
335 data_buffer_[index].dataPtr = nullptr;
philipelc707ab72016-04-01 02:01:54 -0700336 sequence_buffer_[index].used = false;
philipel1f39ba12016-09-21 11:27:47 +0200337 }
philipelf4139332016-04-20 10:26:34 +0200338
philipelc707ab72016-04-01 02:01:54 -0700339 index = (index + 1) % size_;
340 ++seq_num;
341 }
philipelc707ab72016-04-01 02:01:54 -0700342}
343
344bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
345 uint8_t* destination) {
346 rtc::CritScope lock(&crit_);
347
philipelf4139332016-04-20 10:26:34 +0200348 size_t index = frame.first_seq_num() % size_;
349 size_t end = (frame.last_seq_num() + 1) % size_;
350 uint16_t seq_num = frame.first_seq_num();
philipelee13e892017-08-02 02:07:48 -0700351 uint8_t* destination_end = destination + frame.size();
352
353 do {
philipelc707ab72016-04-01 02:01:54 -0700354 if (!sequence_buffer_[index].used ||
355 sequence_buffer_[index].seq_num != seq_num) {
356 return false;
357 }
358
philipelee13e892017-08-02 02:07:48 -0700359 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
philipelc707ab72016-04-01 02:01:54 -0700360 size_t length = data_buffer_[index].sizeBytes;
philipelee13e892017-08-02 02:07:48 -0700361 if (destination + length > destination_end) {
362 LOG(LS_WARNING) << "Frame (" << frame.picture_id << ":"
363 << static_cast<int>(frame.spatial_layer) << ")"
364 << " bitstream buffer is not large enough.";
365 return false;
366 }
367
368 const uint8_t* source = data_buffer_[index].dataPtr;
philipelc707ab72016-04-01 02:01:54 -0700369 memcpy(destination, source, length);
370 destination += length;
371 index = (index + 1) % size_;
372 ++seq_num;
philipelee13e892017-08-02 02:07:48 -0700373 } while (index != end);
374
philipelc707ab72016-04-01 02:01:54 -0700375 return true;
376}
377
philipel02447bc2016-05-13 06:01:03 -0700378VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
philipel02447bc2016-05-13 06:01:03 -0700379 size_t index = seq_num % size_;
380 if (!sequence_buffer_[index].used ||
381 seq_num != sequence_buffer_[index].seq_num) {
382 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200383 }
philipel02447bc2016-05-13 06:01:03 -0700384 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200385}
386
philipel17deeb42016-08-11 15:09:26 +0200387int PacketBuffer::AddRef() const {
388 return rtc::AtomicOps::Increment(&ref_count_);
389}
390
391int PacketBuffer::Release() const {
392 int count = rtc::AtomicOps::Decrement(&ref_count_);
393 if (!count) {
394 delete this;
395 }
396 return count;
397}
398
philipel2c9f9f22017-06-13 02:47:28 -0700399void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {
400 if (!newest_inserted_seq_num_)
401 newest_inserted_seq_num_ = rtc::Optional<uint16_t>(seq_num);
402
403 const int kMaxPaddingAge = 1000;
404 if (AheadOf(seq_num, *newest_inserted_seq_num_)) {
405 uint16_t old_seq_num = seq_num - kMaxPaddingAge;
406 auto erase_to = missing_packets_.lower_bound(old_seq_num);
407 missing_packets_.erase(missing_packets_.begin(), erase_to);
408
409 // Guard against inserting a large amount of missing packets if there is a
410 // jump in the sequence number.
411 if (AheadOf(old_seq_num, *newest_inserted_seq_num_))
412 *newest_inserted_seq_num_ = old_seq_num;
413
414 ++*newest_inserted_seq_num_;
415 while (AheadOf(seq_num, *newest_inserted_seq_num_)) {
416 missing_packets_.insert(*newest_inserted_seq_num_);
417 ++*newest_inserted_seq_num_;
418 }
419 } else {
420 missing_packets_.erase(seq_num);
421 }
422}
423
philipelc707ab72016-04-01 02:01:54 -0700424} // namespace video_coding
425} // namespace webrtc