blob: c5745d2dc23df135800e58d6028b71d69d382dd9 [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"
philipelc707ab72016-04-01 02:01:54 -070019
20namespace webrtc {
21namespace video_coding {
22
23PacketBuffer::PacketBuffer(size_t start_buffer_size,
24 size_t max_buffer_size,
25 OnCompleteFrameCallback* frame_callback)
26 : size_(start_buffer_size),
27 max_size_(max_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070028 first_seq_num_(0),
philipelf4139332016-04-20 10:26:34 +020029 last_seq_num_(0),
30 first_packet_received_(false),
philipelc707ab72016-04-01 02:01:54 -070031 data_buffer_(start_buffer_size),
32 sequence_buffer_(start_buffer_size),
philipel02447bc2016-05-13 06:01:03 -070033 reference_finder_(frame_callback) {
philipelc707ab72016-04-01 02:01:54 -070034 RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
35 // Buffer size must always be a power of 2.
36 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
37 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
38}
39
40bool PacketBuffer::InsertPacket(const VCMPacket& packet) {
41 rtc::CritScope lock(&crit_);
42 uint16_t seq_num = packet.seqNum;
philipelf4139332016-04-20 10:26:34 +020043 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -070044
philipelf4139332016-04-20 10:26:34 +020045 if (!first_packet_received_) {
philipelc707ab72016-04-01 02:01:54 -070046 first_seq_num_ = seq_num - 1;
47 last_seq_num_ = seq_num;
philipelf4139332016-04-20 10:26:34 +020048 first_packet_received_ = true;
philipelc707ab72016-04-01 02:01:54 -070049 }
50
51 if (sequence_buffer_[index].used) {
52 // Duplicate packet, do nothing.
53 if (data_buffer_[index].seqNum == packet.seqNum)
54 return true;
55
56 // The packet buffer is full, try to expand the buffer.
57 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
58 }
59 index = seq_num % size_;
60
61 // Packet buffer is still full.
62 if (sequence_buffer_[index].used)
63 return false;
64 }
65
66 if (AheadOf(seq_num, last_seq_num_))
67 last_seq_num_ = seq_num;
68
philipel9b2ce6b2016-07-05 05:04:46 -070069 // If this is a padding or FEC packet, don't insert it.
70 if (packet.sizeBytes == 0) {
71 reference_finder_.PaddingReceived(packet.seqNum);
72 return true;
73 }
74
philipelc707ab72016-04-01 02:01:54 -070075 sequence_buffer_[index].frame_begin = packet.isFirstPacket;
76 sequence_buffer_[index].frame_end = packet.markerBit;
77 sequence_buffer_[index].seq_num = packet.seqNum;
78 sequence_buffer_[index].continuous = false;
philipelf4139332016-04-20 10:26:34 +020079 sequence_buffer_[index].frame_created = false;
philipelc707ab72016-04-01 02:01:54 -070080 sequence_buffer_[index].used = true;
81 data_buffer_[index] = packet;
82
philipelf4139332016-04-20 10:26:34 +020083 FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -070084 return true;
85}
86
87void PacketBuffer::ClearTo(uint16_t seq_num) {
88 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +020089 size_t index = first_seq_num_ % size_;
philipelc707ab72016-04-01 02:01:54 -070090 while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) {
91 index = (index + 1) % size_;
92 first_seq_num_ = Add<1 << 16>(first_seq_num_, 1);
93 sequence_buffer_[index].used = false;
94 }
95}
96
97bool PacketBuffer::ExpandBufferSize() {
98 if (size_ == max_size_)
99 return false;
100
101 size_t new_size = std::min(max_size_, 2 * size_);
102 std::vector<VCMPacket> new_data_buffer(new_size);
103 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
104 for (size_t i = 0; i < size_; ++i) {
105 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200106 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700107 new_sequence_buffer[index] = sequence_buffer_[i];
108 new_data_buffer[index] = data_buffer_[i];
109 }
110 }
111 size_ = new_size;
112 sequence_buffer_ = std::move(new_sequence_buffer);
113 data_buffer_ = std::move(new_data_buffer);
114 return true;
115}
116
117bool PacketBuffer::IsContinuous(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200118 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700119 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200120
philipelc707ab72016-04-01 02:01:54 -0700121 if (!sequence_buffer_[index].used)
122 return false;
philipelf4139332016-04-20 10:26:34 +0200123 if (sequence_buffer_[index].frame_created)
124 return false;
philipelc707ab72016-04-01 02:01:54 -0700125 if (sequence_buffer_[index].frame_begin)
126 return true;
127 if (!sequence_buffer_[prev_index].used)
128 return false;
philipelf4139332016-04-20 10:26:34 +0200129 if (sequence_buffer_[prev_index].seq_num !=
130 static_cast<uint16_t>(seq_num - 1))
131 return false;
philipelc707ab72016-04-01 02:01:54 -0700132 if (sequence_buffer_[prev_index].continuous)
133 return true;
134
135 return false;
136}
137
philipelf4139332016-04-20 10:26:34 +0200138void PacketBuffer::FindFrames(uint16_t seq_num) {
139 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700140 while (IsContinuous(seq_num)) {
141 sequence_buffer_[index].continuous = true;
142
philipelf4139332016-04-20 10:26:34 +0200143 // If all packets of the frame is continuous, find the first packet of the
144 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700145 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200146 size_t frame_size = 0;
147 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700148 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200149
philipel5ceaaae2016-05-24 10:20:47 +0200150 // Find the start index by searching backward until the packet with
151 // the |frame_begin| flag is set.
152 int start_index = index;
153 while (true) {
154 frame_size += data_buffer_[start_index].sizeBytes;
155 max_nack_count = std::max(
156 max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200157 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200158
159 if (sequence_buffer_[start_index].frame_begin)
160 break;
161
philipelf4139332016-04-20 10:26:34 +0200162 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipelc707ab72016-04-01 02:01:54 -0700163 start_seq_num--;
164 }
165
philipel5ceaaae2016-05-24 10:20:47 +0200166 std::unique_ptr<RtpFrameObject> frame(new RtpFrameObject(
167 this, start_seq_num, seq_num, frame_size, max_nack_count));
philipel02447bc2016-05-13 06:01:03 -0700168 reference_finder_.ManageFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700169 }
170
171 index = (index + 1) % size_;
172 ++seq_num;
173 }
174}
175
176void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
177 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200178 size_t index = frame->first_seq_num() % size_;
179 size_t end = (frame->last_seq_num() + 1) % size_;
180 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700181 while (index != end) {
philipelf4139332016-04-20 10:26:34 +0200182 if (sequence_buffer_[index].seq_num == seq_num)
philipelc707ab72016-04-01 02:01:54 -0700183 sequence_buffer_[index].used = false;
philipelf4139332016-04-20 10:26:34 +0200184
philipelc707ab72016-04-01 02:01:54 -0700185 index = (index + 1) % size_;
186 ++seq_num;
187 }
188
189 index = first_seq_num_ % size_;
190 while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) &&
191 !sequence_buffer_[index].used) {
192 ++first_seq_num_;
193 index = (index + 1) % size_;
194 }
195}
196
197bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
198 uint8_t* destination) {
199 rtc::CritScope lock(&crit_);
200
philipelf4139332016-04-20 10:26:34 +0200201 size_t index = frame.first_seq_num() % size_;
202 size_t end = (frame.last_seq_num() + 1) % size_;
203 uint16_t seq_num = frame.first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700204 while (index != end) {
205 if (!sequence_buffer_[index].used ||
206 sequence_buffer_[index].seq_num != seq_num) {
207 return false;
208 }
209
210 const uint8_t* source = data_buffer_[index].dataPtr;
211 size_t length = data_buffer_[index].sizeBytes;
212 memcpy(destination, source, length);
213 destination += length;
214 index = (index + 1) % size_;
215 ++seq_num;
216 }
217 return true;
218}
219
philipel02447bc2016-05-13 06:01:03 -0700220VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
221 rtc::CritScope lock(&crit_);
222 size_t index = seq_num % size_;
223 if (!sequence_buffer_[index].used ||
224 seq_num != sequence_buffer_[index].seq_num) {
225 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200226 }
philipel02447bc2016-05-13 06:01:03 -0700227 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200228}
229
philipel02447bc2016-05-13 06:01:03 -0700230void PacketBuffer::Clear() {
philipelc707ab72016-04-01 02:01:54 -0700231 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200232 for (size_t i = 0; i < size_; ++i)
philipelc707ab72016-04-01 02:01:54 -0700233 sequence_buffer_[i].used = false;
philipelf4139332016-04-20 10:26:34 +0200234
philipelf4139332016-04-20 10:26:34 +0200235 first_packet_received_ = false;
philipelc707ab72016-04-01 02:01:54 -0700236}
237
238} // namespace video_coding
239} // namespace webrtc