blob: 0d36b9c3c97ea439c714cf7f8b37656bc563326d [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
philipelf4139332016-04-20 10:26:34 +020093 FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -070094 return true;
95}
96
97void PacketBuffer::ClearTo(uint16_t seq_num) {
98 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +020099 size_t index = first_seq_num_ % size_;
philipelc707ab72016-04-01 02:01:54 -0700100 while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) {
101 index = (index + 1) % size_;
102 first_seq_num_ = Add<1 << 16>(first_seq_num_, 1);
103 sequence_buffer_[index].used = false;
104 }
105}
106
107bool PacketBuffer::ExpandBufferSize() {
108 if (size_ == max_size_)
109 return false;
110
111 size_t new_size = std::min(max_size_, 2 * size_);
112 std::vector<VCMPacket> new_data_buffer(new_size);
113 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
114 for (size_t i = 0; i < size_; ++i) {
115 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200116 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700117 new_sequence_buffer[index] = sequence_buffer_[i];
118 new_data_buffer[index] = data_buffer_[i];
119 }
120 }
121 size_ = new_size;
122 sequence_buffer_ = std::move(new_sequence_buffer);
123 data_buffer_ = std::move(new_data_buffer);
124 return true;
125}
126
127bool PacketBuffer::IsContinuous(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200128 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700129 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200130
philipelc707ab72016-04-01 02:01:54 -0700131 if (!sequence_buffer_[index].used)
132 return false;
philipelf4139332016-04-20 10:26:34 +0200133 if (sequence_buffer_[index].frame_created)
134 return false;
philipelc707ab72016-04-01 02:01:54 -0700135 if (sequence_buffer_[index].frame_begin)
136 return true;
137 if (!sequence_buffer_[prev_index].used)
138 return false;
philipelf4139332016-04-20 10:26:34 +0200139 if (sequence_buffer_[prev_index].seq_num !=
140 static_cast<uint16_t>(seq_num - 1))
141 return false;
philipelc707ab72016-04-01 02:01:54 -0700142 if (sequence_buffer_[prev_index].continuous)
143 return true;
144
145 return false;
146}
147
philipelf4139332016-04-20 10:26:34 +0200148void PacketBuffer::FindFrames(uint16_t seq_num) {
149 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700150 while (IsContinuous(seq_num)) {
151 sequence_buffer_[index].continuous = true;
152
philipelf4139332016-04-20 10:26:34 +0200153 // If all packets of the frame is continuous, find the first packet of the
154 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700155 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200156 size_t frame_size = 0;
157 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700158 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200159
philipel5ceaaae2016-05-24 10:20:47 +0200160 // Find the start index by searching backward until the packet with
161 // the |frame_begin| flag is set.
162 int start_index = index;
163 while (true) {
164 frame_size += data_buffer_[start_index].sizeBytes;
165 max_nack_count = std::max(
166 max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200167 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200168
169 if (sequence_buffer_[start_index].frame_begin)
170 break;
171
philipelf4139332016-04-20 10:26:34 +0200172 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipelc707ab72016-04-01 02:01:54 -0700173 start_seq_num--;
174 }
175
philipelb4d31082016-07-11 08:46:29 -0700176 std::unique_ptr<RtpFrameObject> frame(
177 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
178 max_nack_count, clock_->TimeInMilliseconds()));
philipel17deeb42016-08-11 15:09:26 +0200179
180 received_frame_callback_->OnReceivedFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700181 }
182
183 index = (index + 1) % size_;
184 ++seq_num;
185 }
186}
187
188void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
189 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200190 size_t index = frame->first_seq_num() % size_;
191 size_t end = (frame->last_seq_num() + 1) % size_;
192 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700193 while (index != end) {
philipelf4139332016-04-20 10:26:34 +0200194 if (sequence_buffer_[index].seq_num == seq_num)
philipelc707ab72016-04-01 02:01:54 -0700195 sequence_buffer_[index].used = false;
philipelf4139332016-04-20 10:26:34 +0200196
philipelc707ab72016-04-01 02:01:54 -0700197 index = (index + 1) % size_;
198 ++seq_num;
199 }
200
201 index = first_seq_num_ % size_;
202 while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) &&
203 !sequence_buffer_[index].used) {
204 ++first_seq_num_;
205 index = (index + 1) % size_;
206 }
207}
208
209bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
210 uint8_t* destination) {
211 rtc::CritScope lock(&crit_);
212
philipelf4139332016-04-20 10:26:34 +0200213 size_t index = frame.first_seq_num() % size_;
214 size_t end = (frame.last_seq_num() + 1) % size_;
215 uint16_t seq_num = frame.first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700216 while (index != end) {
217 if (!sequence_buffer_[index].used ||
218 sequence_buffer_[index].seq_num != seq_num) {
219 return false;
220 }
221
222 const uint8_t* source = data_buffer_[index].dataPtr;
223 size_t length = data_buffer_[index].sizeBytes;
224 memcpy(destination, source, length);
225 destination += length;
226 index = (index + 1) % size_;
227 ++seq_num;
228 }
229 return true;
230}
231
philipel02447bc2016-05-13 06:01:03 -0700232VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
233 rtc::CritScope lock(&crit_);
234 size_t index = seq_num % size_;
235 if (!sequence_buffer_[index].used ||
236 seq_num != sequence_buffer_[index].seq_num) {
237 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200238 }
philipel02447bc2016-05-13 06:01:03 -0700239 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200240}
241
philipel02447bc2016-05-13 06:01:03 -0700242void PacketBuffer::Clear() {
philipelc707ab72016-04-01 02:01:54 -0700243 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200244 for (size_t i = 0; i < size_; ++i)
philipelc707ab72016-04-01 02:01:54 -0700245 sequence_buffer_[i].used = false;
philipelf4139332016-04-20 10:26:34 +0200246
philipelf4139332016-04-20 10:26:34 +0200247 first_packet_received_ = false;
philipelc707ab72016-04-01 02:01:54 -0700248}
249
philipel17deeb42016-08-11 15:09:26 +0200250int PacketBuffer::AddRef() const {
251 return rtc::AtomicOps::Increment(&ref_count_);
252}
253
254int PacketBuffer::Release() const {
255 int count = rtc::AtomicOps::Decrement(&ref_count_);
256 if (!count) {
257 delete this;
258 }
259 return count;
260}
261
philipelc707ab72016-04-01 02:01:54 -0700262} // namespace video_coding
263} // namespace webrtc