blob: ad0054fa84deba79c231f6e3c4aa8160192ac036 [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
69 sequence_buffer_[index].frame_begin = packet.isFirstPacket;
70 sequence_buffer_[index].frame_end = packet.markerBit;
71 sequence_buffer_[index].seq_num = packet.seqNum;
72 sequence_buffer_[index].continuous = false;
philipelf4139332016-04-20 10:26:34 +020073 sequence_buffer_[index].frame_created = false;
philipelc707ab72016-04-01 02:01:54 -070074 sequence_buffer_[index].used = true;
75 data_buffer_[index] = packet;
76
philipelf4139332016-04-20 10:26:34 +020077 FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -070078 return true;
79}
80
81void PacketBuffer::ClearTo(uint16_t seq_num) {
82 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +020083 size_t index = first_seq_num_ % size_;
philipelc707ab72016-04-01 02:01:54 -070084 while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) {
85 index = (index + 1) % size_;
86 first_seq_num_ = Add<1 << 16>(first_seq_num_, 1);
87 sequence_buffer_[index].used = false;
88 }
89}
90
91bool PacketBuffer::ExpandBufferSize() {
92 if (size_ == max_size_)
93 return false;
94
95 size_t new_size = std::min(max_size_, 2 * size_);
96 std::vector<VCMPacket> new_data_buffer(new_size);
97 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
98 for (size_t i = 0; i < size_; ++i) {
99 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200100 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700101 new_sequence_buffer[index] = sequence_buffer_[i];
102 new_data_buffer[index] = data_buffer_[i];
103 }
104 }
105 size_ = new_size;
106 sequence_buffer_ = std::move(new_sequence_buffer);
107 data_buffer_ = std::move(new_data_buffer);
108 return true;
109}
110
111bool PacketBuffer::IsContinuous(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200112 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700113 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200114
philipelc707ab72016-04-01 02:01:54 -0700115 if (!sequence_buffer_[index].used)
116 return false;
philipelf4139332016-04-20 10:26:34 +0200117 if (sequence_buffer_[index].frame_created)
118 return false;
philipelc707ab72016-04-01 02:01:54 -0700119 if (sequence_buffer_[index].frame_begin)
120 return true;
121 if (!sequence_buffer_[prev_index].used)
122 return false;
philipelf4139332016-04-20 10:26:34 +0200123 if (sequence_buffer_[prev_index].seq_num !=
124 static_cast<uint16_t>(seq_num - 1))
125 return false;
philipelc707ab72016-04-01 02:01:54 -0700126 if (sequence_buffer_[prev_index].continuous)
127 return true;
128
129 return false;
130}
131
philipelf4139332016-04-20 10:26:34 +0200132void PacketBuffer::FindFrames(uint16_t seq_num) {
133 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700134 while (IsContinuous(seq_num)) {
135 sequence_buffer_[index].continuous = true;
136
philipelf4139332016-04-20 10:26:34 +0200137 // If all packets of the frame is continuous, find the first packet of the
138 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700139 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200140 size_t frame_size = 0;
141 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700142 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200143
philipel5ceaaae2016-05-24 10:20:47 +0200144 // Find the start index by searching backward until the packet with
145 // the |frame_begin| flag is set.
146 int start_index = index;
147 while (true) {
148 frame_size += data_buffer_[start_index].sizeBytes;
149 max_nack_count = std::max(
150 max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200151 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200152
153 if (sequence_buffer_[start_index].frame_begin)
154 break;
155
philipelf4139332016-04-20 10:26:34 +0200156 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipelc707ab72016-04-01 02:01:54 -0700157 start_seq_num--;
158 }
159
philipel5ceaaae2016-05-24 10:20:47 +0200160 std::unique_ptr<RtpFrameObject> frame(new RtpFrameObject(
161 this, start_seq_num, seq_num, frame_size, max_nack_count));
philipel02447bc2016-05-13 06:01:03 -0700162 reference_finder_.ManageFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700163 }
164
165 index = (index + 1) % size_;
166 ++seq_num;
167 }
168}
169
170void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
171 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200172 size_t index = frame->first_seq_num() % size_;
173 size_t end = (frame->last_seq_num() + 1) % size_;
174 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700175 while (index != end) {
philipelf4139332016-04-20 10:26:34 +0200176 if (sequence_buffer_[index].seq_num == seq_num)
philipelc707ab72016-04-01 02:01:54 -0700177 sequence_buffer_[index].used = false;
philipelf4139332016-04-20 10:26:34 +0200178
philipelc707ab72016-04-01 02:01:54 -0700179 index = (index + 1) % size_;
180 ++seq_num;
181 }
182
183 index = first_seq_num_ % size_;
184 while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) &&
185 !sequence_buffer_[index].used) {
186 ++first_seq_num_;
187 index = (index + 1) % size_;
188 }
189}
190
191bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
192 uint8_t* destination) {
193 rtc::CritScope lock(&crit_);
194
philipelf4139332016-04-20 10:26:34 +0200195 size_t index = frame.first_seq_num() % size_;
196 size_t end = (frame.last_seq_num() + 1) % size_;
197 uint16_t seq_num = frame.first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700198 while (index != end) {
199 if (!sequence_buffer_[index].used ||
200 sequence_buffer_[index].seq_num != seq_num) {
201 return false;
202 }
203
204 const uint8_t* source = data_buffer_[index].dataPtr;
205 size_t length = data_buffer_[index].sizeBytes;
206 memcpy(destination, source, length);
207 destination += length;
208 index = (index + 1) % size_;
209 ++seq_num;
210 }
211 return true;
212}
213
philipel02447bc2016-05-13 06:01:03 -0700214VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
215 rtc::CritScope lock(&crit_);
216 size_t index = seq_num % size_;
217 if (!sequence_buffer_[index].used ||
218 seq_num != sequence_buffer_[index].seq_num) {
219 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200220 }
philipel02447bc2016-05-13 06:01:03 -0700221 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200222}
223
philipel02447bc2016-05-13 06:01:03 -0700224void PacketBuffer::Clear() {
philipelc707ab72016-04-01 02:01:54 -0700225 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200226 for (size_t i = 0; i < size_; ++i)
philipelc707ab72016-04-01 02:01:54 -0700227 sequence_buffer_[i].used = false;
philipelf4139332016-04-20 10:26:34 +0200228
philipelf4139332016-04-20 10:26:34 +0200229 first_packet_received_ = false;
philipelc707ab72016-04-01 02:01:54 -0700230}
231
232} // namespace video_coding
233} // namespace webrtc