blob: bd0cf75548eeb2203de6f467762f30164aafa7a1 [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
philipel17deeb42016-08-11 15:09:26 +020017#include "webrtc/base/atomicops.h"
philipelc707ab72016-04-01 02:01:54 -070018#include "webrtc/base/checks.h"
philipela1059872016-05-09 11:41:48 +020019#include "webrtc/base/logging.h"
philipelc707ab72016-04-01 02:01:54 -070020#include "webrtc/modules/video_coding/frame_object.h"
philipelb4d31082016-07-11 08:46:29 -070021#include "webrtc/system_wrappers/include/clock.h"
philipelc707ab72016-04-01 02:01:54 -070022
23namespace webrtc {
24namespace video_coding {
25
philipel17deeb42016-08-11 15:09:26 +020026rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create(
27 Clock* clock,
28 size_t start_buffer_size,
29 size_t max_buffer_size,
30 OnReceivedFrameCallback* received_frame_callback) {
31 return rtc::scoped_refptr<PacketBuffer>(new PacketBuffer(
32 clock, start_buffer_size, max_buffer_size, received_frame_callback));
33}
34
philipelb4d31082016-07-11 08:46:29 -070035PacketBuffer::PacketBuffer(Clock* clock,
36 size_t start_buffer_size,
philipelc707ab72016-04-01 02:01:54 -070037 size_t max_buffer_size,
philipel17deeb42016-08-11 15:09:26 +020038 OnReceivedFrameCallback* received_frame_callback)
philipelb4d31082016-07-11 08:46:29 -070039 : clock_(clock),
40 size_(start_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070041 max_size_(max_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070042 first_seq_num_(0),
philipelf4139332016-04-20 10:26:34 +020043 last_seq_num_(0),
44 first_packet_received_(false),
philipelc707ab72016-04-01 02:01:54 -070045 data_buffer_(start_buffer_size),
46 sequence_buffer_(start_buffer_size),
philipel17deeb42016-08-11 15:09:26 +020047 received_frame_callback_(received_frame_callback) {
philipelc707ab72016-04-01 02:01:54 -070048 RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
49 // Buffer size must always be a power of 2.
50 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
51 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
52}
53
philipel17deeb42016-08-11 15:09:26 +020054PacketBuffer::~PacketBuffer() {}
55
philipelc707ab72016-04-01 02:01:54 -070056bool PacketBuffer::InsertPacket(const VCMPacket& packet) {
57 rtc::CritScope lock(&crit_);
58 uint16_t seq_num = packet.seqNum;
philipelf4139332016-04-20 10:26:34 +020059 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -070060
philipelf4139332016-04-20 10:26:34 +020061 if (!first_packet_received_) {
philipelc707ab72016-04-01 02:01:54 -070062 first_seq_num_ = seq_num - 1;
63 last_seq_num_ = seq_num;
philipelf4139332016-04-20 10:26:34 +020064 first_packet_received_ = true;
philipelc707ab72016-04-01 02:01:54 -070065 }
66
67 if (sequence_buffer_[index].used) {
68 // Duplicate packet, do nothing.
69 if (data_buffer_[index].seqNum == packet.seqNum)
70 return true;
71
72 // The packet buffer is full, try to expand the buffer.
73 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
74 }
75 index = seq_num % size_;
76
77 // Packet buffer is still full.
78 if (sequence_buffer_[index].used)
79 return false;
80 }
81
82 if (AheadOf(seq_num, last_seq_num_))
83 last_seq_num_ = seq_num;
84
85 sequence_buffer_[index].frame_begin = packet.isFirstPacket;
86 sequence_buffer_[index].frame_end = packet.markerBit;
87 sequence_buffer_[index].seq_num = packet.seqNum;
88 sequence_buffer_[index].continuous = false;
philipelf4139332016-04-20 10:26:34 +020089 sequence_buffer_[index].frame_created = false;
philipelc707ab72016-04-01 02:01:54 -070090 sequence_buffer_[index].used = true;
91 data_buffer_[index] = packet;
92
philipel1f39ba12016-09-21 11:27:47 +020093 // Since the data pointed to by |packet.dataPtr| is non-persistent the
94 // data has to be copied to its own buffer.
95 // TODO(philipel): Take ownership instead of copying payload when
96 // bitstream-fixing has been implemented.
97 if (packet.sizeBytes) {
98 uint8_t* payload = new uint8_t[packet.sizeBytes];
99 memcpy(payload, packet.dataPtr, packet.sizeBytes);
100 data_buffer_[index].dataPtr = payload;
101 }
102
philipelf4139332016-04-20 10:26:34 +0200103 FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -0700104 return true;
105}
106
107void PacketBuffer::ClearTo(uint16_t seq_num) {
108 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200109 size_t index = first_seq_num_ % size_;
philipelc707ab72016-04-01 02:01:54 -0700110 while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) {
111 index = (index + 1) % size_;
philipel1f39ba12016-09-21 11:27:47 +0200112 ++first_seq_num_;
113 delete[] data_buffer_[index].dataPtr;
114 data_buffer_[index].dataPtr = nullptr;
philipelc707ab72016-04-01 02:01:54 -0700115 sequence_buffer_[index].used = false;
116 }
117}
118
119bool PacketBuffer::ExpandBufferSize() {
120 if (size_ == max_size_)
121 return false;
122
123 size_t new_size = std::min(max_size_, 2 * size_);
124 std::vector<VCMPacket> new_data_buffer(new_size);
125 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
126 for (size_t i = 0; i < size_; ++i) {
127 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200128 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700129 new_sequence_buffer[index] = sequence_buffer_[i];
130 new_data_buffer[index] = data_buffer_[i];
131 }
132 }
133 size_ = new_size;
134 sequence_buffer_ = std::move(new_sequence_buffer);
135 data_buffer_ = std::move(new_data_buffer);
136 return true;
137}
138
139bool PacketBuffer::IsContinuous(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200140 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700141 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200142
philipelc707ab72016-04-01 02:01:54 -0700143 if (!sequence_buffer_[index].used)
144 return false;
philipelf4139332016-04-20 10:26:34 +0200145 if (sequence_buffer_[index].frame_created)
146 return false;
philipelc707ab72016-04-01 02:01:54 -0700147 if (sequence_buffer_[index].frame_begin)
148 return true;
149 if (!sequence_buffer_[prev_index].used)
150 return false;
philipelf4139332016-04-20 10:26:34 +0200151 if (sequence_buffer_[prev_index].seq_num !=
152 static_cast<uint16_t>(seq_num - 1))
153 return false;
philipelc707ab72016-04-01 02:01:54 -0700154 if (sequence_buffer_[prev_index].continuous)
155 return true;
156
157 return false;
158}
159
philipelf4139332016-04-20 10:26:34 +0200160void PacketBuffer::FindFrames(uint16_t seq_num) {
161 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700162 while (IsContinuous(seq_num)) {
163 sequence_buffer_[index].continuous = true;
164
philipelf4139332016-04-20 10:26:34 +0200165 // If all packets of the frame is continuous, find the first packet of the
166 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700167 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200168 size_t frame_size = 0;
169 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700170 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200171
philipel5ceaaae2016-05-24 10:20:47 +0200172 // Find the start index by searching backward until the packet with
173 // the |frame_begin| flag is set.
174 int start_index = index;
175 while (true) {
176 frame_size += data_buffer_[start_index].sizeBytes;
177 max_nack_count = std::max(
178 max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200179 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200180
181 if (sequence_buffer_[start_index].frame_begin)
182 break;
183
philipelf4139332016-04-20 10:26:34 +0200184 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipelc707ab72016-04-01 02:01:54 -0700185 start_seq_num--;
186 }
187
philipelb4d31082016-07-11 08:46:29 -0700188 std::unique_ptr<RtpFrameObject> frame(
189 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
190 max_nack_count, clock_->TimeInMilliseconds()));
philipel17deeb42016-08-11 15:09:26 +0200191
192 received_frame_callback_->OnReceivedFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700193 }
194
195 index = (index + 1) % size_;
196 ++seq_num;
197 }
198}
199
200void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
201 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200202 size_t index = frame->first_seq_num() % size_;
203 size_t end = (frame->last_seq_num() + 1) % size_;
204 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700205 while (index != end) {
philipel1f39ba12016-09-21 11:27:47 +0200206 if (sequence_buffer_[index].seq_num == seq_num) {
207 delete[] data_buffer_[index].dataPtr;
208 data_buffer_[index].dataPtr = nullptr;
philipelc707ab72016-04-01 02:01:54 -0700209 sequence_buffer_[index].used = false;
philipel1f39ba12016-09-21 11:27:47 +0200210 }
philipelf4139332016-04-20 10:26:34 +0200211
philipelc707ab72016-04-01 02:01:54 -0700212 index = (index + 1) % size_;
213 ++seq_num;
214 }
215
216 index = first_seq_num_ % size_;
217 while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) &&
218 !sequence_buffer_[index].used) {
219 ++first_seq_num_;
220 index = (index + 1) % size_;
221 }
222}
223
224bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
225 uint8_t* destination) {
226 rtc::CritScope lock(&crit_);
227
philipelf4139332016-04-20 10:26:34 +0200228 size_t index = frame.first_seq_num() % size_;
229 size_t end = (frame.last_seq_num() + 1) % size_;
230 uint16_t seq_num = frame.first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700231 while (index != end) {
232 if (!sequence_buffer_[index].used ||
233 sequence_buffer_[index].seq_num != seq_num) {
234 return false;
235 }
236
237 const uint8_t* source = data_buffer_[index].dataPtr;
238 size_t length = data_buffer_[index].sizeBytes;
239 memcpy(destination, source, length);
240 destination += length;
241 index = (index + 1) % size_;
242 ++seq_num;
243 }
244 return true;
245}
246
philipel02447bc2016-05-13 06:01:03 -0700247VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
248 rtc::CritScope lock(&crit_);
249 size_t index = seq_num % size_;
250 if (!sequence_buffer_[index].used ||
251 seq_num != sequence_buffer_[index].seq_num) {
252 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200253 }
philipel02447bc2016-05-13 06:01:03 -0700254 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200255}
256
philipel02447bc2016-05-13 06:01:03 -0700257void PacketBuffer::Clear() {
philipelc707ab72016-04-01 02:01:54 -0700258 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200259 for (size_t i = 0; i < size_; ++i)
philipelc707ab72016-04-01 02:01:54 -0700260 sequence_buffer_[i].used = false;
philipelf4139332016-04-20 10:26:34 +0200261
philipelf4139332016-04-20 10:26:34 +0200262 first_packet_received_ = false;
philipelc707ab72016-04-01 02:01:54 -0700263}
264
philipel17deeb42016-08-11 15:09:26 +0200265int PacketBuffer::AddRef() const {
266 return rtc::AtomicOps::Increment(&ref_count_);
267}
268
269int PacketBuffer::Release() const {
270 int count = rtc::AtomicOps::Decrement(&ref_count_);
271 if (!count) {
272 delete this;
273 }
274 return count;
275}
276
philipelc707ab72016-04-01 02:01:54 -0700277} // namespace video_coding
278} // namespace webrtc