blob: df173504ff79af6be8ee667269e84596a45f270e [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>
15
16#include "webrtc/base/checks.h"
philipela1059872016-05-09 11:41:48 +020017#include "webrtc/base/logging.h"
philipelc707ab72016-04-01 02:01:54 -070018#include "webrtc/modules/video_coding/frame_object.h"
philipelb4d31082016-07-11 08:46:29 -070019#include "webrtc/system_wrappers/include/clock.h"
philipelc707ab72016-04-01 02:01:54 -070020
21namespace webrtc {
22namespace video_coding {
23
philipelb4d31082016-07-11 08:46:29 -070024PacketBuffer::PacketBuffer(Clock* clock,
25 size_t start_buffer_size,
philipelc707ab72016-04-01 02:01:54 -070026 size_t max_buffer_size,
27 OnCompleteFrameCallback* frame_callback)
philipelb4d31082016-07-11 08:46:29 -070028 : clock_(clock),
29 size_(start_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070030 max_size_(max_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070031 first_seq_num_(0),
philipelf4139332016-04-20 10:26:34 +020032 last_seq_num_(0),
33 first_packet_received_(false),
philipelc707ab72016-04-01 02:01:54 -070034 data_buffer_(start_buffer_size),
35 sequence_buffer_(start_buffer_size),
philipel02447bc2016-05-13 06:01:03 -070036 reference_finder_(frame_callback) {
philipelc707ab72016-04-01 02:01:54 -070037 RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
38 // Buffer size must always be a power of 2.
39 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
40 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
41}
42
43bool PacketBuffer::InsertPacket(const VCMPacket& packet) {
44 rtc::CritScope lock(&crit_);
45 uint16_t seq_num = packet.seqNum;
philipelf4139332016-04-20 10:26:34 +020046 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -070047
philipelf4139332016-04-20 10:26:34 +020048 if (!first_packet_received_) {
philipelc707ab72016-04-01 02:01:54 -070049 first_seq_num_ = seq_num - 1;
50 last_seq_num_ = seq_num;
philipelf4139332016-04-20 10:26:34 +020051 first_packet_received_ = true;
philipelc707ab72016-04-01 02:01:54 -070052 }
53
54 if (sequence_buffer_[index].used) {
55 // Duplicate packet, do nothing.
56 if (data_buffer_[index].seqNum == packet.seqNum)
57 return true;
58
59 // The packet buffer is full, try to expand the buffer.
60 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
61 }
62 index = seq_num % size_;
63
64 // Packet buffer is still full.
65 if (sequence_buffer_[index].used)
66 return false;
67 }
68
69 if (AheadOf(seq_num, last_seq_num_))
70 last_seq_num_ = seq_num;
71
philipel9b2ce6b2016-07-05 05:04:46 -070072 // If this is a padding or FEC packet, don't insert it.
73 if (packet.sizeBytes == 0) {
74 reference_finder_.PaddingReceived(packet.seqNum);
75 return true;
76 }
77
philipelc707ab72016-04-01 02:01:54 -070078 sequence_buffer_[index].frame_begin = packet.isFirstPacket;
79 sequence_buffer_[index].frame_end = packet.markerBit;
80 sequence_buffer_[index].seq_num = packet.seqNum;
81 sequence_buffer_[index].continuous = false;
philipelf4139332016-04-20 10:26:34 +020082 sequence_buffer_[index].frame_created = false;
philipelc707ab72016-04-01 02:01:54 -070083 sequence_buffer_[index].used = true;
84 data_buffer_[index] = packet;
85
philipelf4139332016-04-20 10:26:34 +020086 FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -070087 return true;
88}
89
90void PacketBuffer::ClearTo(uint16_t seq_num) {
91 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +020092 size_t index = first_seq_num_ % size_;
philipelc707ab72016-04-01 02:01:54 -070093 while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) {
94 index = (index + 1) % size_;
95 first_seq_num_ = Add<1 << 16>(first_seq_num_, 1);
96 sequence_buffer_[index].used = false;
97 }
98}
99
100bool PacketBuffer::ExpandBufferSize() {
101 if (size_ == max_size_)
102 return false;
103
104 size_t new_size = std::min(max_size_, 2 * size_);
105 std::vector<VCMPacket> new_data_buffer(new_size);
106 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
107 for (size_t i = 0; i < size_; ++i) {
108 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200109 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700110 new_sequence_buffer[index] = sequence_buffer_[i];
111 new_data_buffer[index] = data_buffer_[i];
112 }
113 }
114 size_ = new_size;
115 sequence_buffer_ = std::move(new_sequence_buffer);
116 data_buffer_ = std::move(new_data_buffer);
117 return true;
118}
119
120bool PacketBuffer::IsContinuous(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200121 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700122 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200123
philipelc707ab72016-04-01 02:01:54 -0700124 if (!sequence_buffer_[index].used)
125 return false;
philipelf4139332016-04-20 10:26:34 +0200126 if (sequence_buffer_[index].frame_created)
127 return false;
philipelc707ab72016-04-01 02:01:54 -0700128 if (sequence_buffer_[index].frame_begin)
129 return true;
130 if (!sequence_buffer_[prev_index].used)
131 return false;
philipelf4139332016-04-20 10:26:34 +0200132 if (sequence_buffer_[prev_index].seq_num !=
133 static_cast<uint16_t>(seq_num - 1))
134 return false;
philipelc707ab72016-04-01 02:01:54 -0700135 if (sequence_buffer_[prev_index].continuous)
136 return true;
137
138 return false;
139}
140
philipelf4139332016-04-20 10:26:34 +0200141void PacketBuffer::FindFrames(uint16_t seq_num) {
142 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700143 while (IsContinuous(seq_num)) {
144 sequence_buffer_[index].continuous = true;
145
philipelf4139332016-04-20 10:26:34 +0200146 // If all packets of the frame is continuous, find the first packet of the
147 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700148 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200149 size_t frame_size = 0;
150 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700151 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200152
philipel5ceaaae2016-05-24 10:20:47 +0200153 // Find the start index by searching backward until the packet with
154 // the |frame_begin| flag is set.
155 int start_index = index;
156 while (true) {
157 frame_size += data_buffer_[start_index].sizeBytes;
158 max_nack_count = std::max(
159 max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200160 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200161
162 if (sequence_buffer_[start_index].frame_begin)
163 break;
164
philipelf4139332016-04-20 10:26:34 +0200165 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipelc707ab72016-04-01 02:01:54 -0700166 start_seq_num--;
167 }
168
philipelb4d31082016-07-11 08:46:29 -0700169 std::unique_ptr<RtpFrameObject> frame(
170 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
171 max_nack_count, clock_->TimeInMilliseconds()));
philipel02447bc2016-05-13 06:01:03 -0700172 reference_finder_.ManageFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700173 }
174
175 index = (index + 1) % size_;
176 ++seq_num;
177 }
178}
179
180void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
181 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200182 size_t index = frame->first_seq_num() % size_;
183 size_t end = (frame->last_seq_num() + 1) % size_;
184 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700185 while (index != end) {
philipelf4139332016-04-20 10:26:34 +0200186 if (sequence_buffer_[index].seq_num == seq_num)
philipelc707ab72016-04-01 02:01:54 -0700187 sequence_buffer_[index].used = false;
philipelf4139332016-04-20 10:26:34 +0200188
philipelc707ab72016-04-01 02:01:54 -0700189 index = (index + 1) % size_;
190 ++seq_num;
191 }
192
193 index = first_seq_num_ % size_;
194 while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) &&
195 !sequence_buffer_[index].used) {
196 ++first_seq_num_;
197 index = (index + 1) % size_;
198 }
199}
200
201bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
202 uint8_t* destination) {
203 rtc::CritScope lock(&crit_);
204
philipelf4139332016-04-20 10:26:34 +0200205 size_t index = frame.first_seq_num() % size_;
206 size_t end = (frame.last_seq_num() + 1) % size_;
207 uint16_t seq_num = frame.first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700208 while (index != end) {
209 if (!sequence_buffer_[index].used ||
210 sequence_buffer_[index].seq_num != seq_num) {
211 return false;
212 }
213
214 const uint8_t* source = data_buffer_[index].dataPtr;
215 size_t length = data_buffer_[index].sizeBytes;
216 memcpy(destination, source, length);
217 destination += length;
218 index = (index + 1) % size_;
219 ++seq_num;
220 }
221 return true;
222}
223
philipel02447bc2016-05-13 06:01:03 -0700224VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
225 rtc::CritScope lock(&crit_);
226 size_t index = seq_num % size_;
227 if (!sequence_buffer_[index].used ||
228 seq_num != sequence_buffer_[index].seq_num) {
229 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200230 }
philipel02447bc2016-05-13 06:01:03 -0700231 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200232}
233
philipel02447bc2016-05-13 06:01:03 -0700234void PacketBuffer::Clear() {
philipelc707ab72016-04-01 02:01:54 -0700235 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200236 for (size_t i = 0; i < size_; ++i)
philipelc707ab72016-04-01 02:01:54 -0700237 sequence_buffer_[i].used = false;
philipelf4139332016-04-20 10:26:34 +0200238
philipelf4139332016-04-20 10:26:34 +0200239 first_packet_received_ = false;
philipelc707ab72016-04-01 02:01:54 -0700240}
241
242} // namespace video_coding
243} // namespace webrtc