blob: 09fb2499074fde1b12005d427b9cdba5dd81a18c [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) {
philipelf4139332016-04-20 10:26:34 +0200140 int start_index = index;
philipelc707ab72016-04-01 02:01:54 -0700141 uint16_t start_seq_num = seq_num;
philipelf4139332016-04-20 10:26:34 +0200142
143 while (!sequence_buffer_[start_index].frame_begin) {
144 sequence_buffer_[start_index].frame_created = true;
145 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipelc707ab72016-04-01 02:01:54 -0700146 start_seq_num--;
147 }
philipelf4139332016-04-20 10:26:34 +0200148 sequence_buffer_[start_index].frame_created = true;
philipelc707ab72016-04-01 02:01:54 -0700149
philipelf4139332016-04-20 10:26:34 +0200150 std::unique_ptr<RtpFrameObject> frame(
151 new RtpFrameObject(this, start_seq_num, seq_num));
philipel02447bc2016-05-13 06:01:03 -0700152 reference_finder_.ManageFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700153 }
154
155 index = (index + 1) % size_;
156 ++seq_num;
157 }
158}
159
160void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
161 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200162 size_t index = frame->first_seq_num() % size_;
163 size_t end = (frame->last_seq_num() + 1) % size_;
164 uint16_t seq_num = frame->first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700165 while (index != end) {
philipelf4139332016-04-20 10:26:34 +0200166 if (sequence_buffer_[index].seq_num == seq_num)
philipelc707ab72016-04-01 02:01:54 -0700167 sequence_buffer_[index].used = false;
philipelf4139332016-04-20 10:26:34 +0200168
philipelc707ab72016-04-01 02:01:54 -0700169 index = (index + 1) % size_;
170 ++seq_num;
171 }
172
173 index = first_seq_num_ % size_;
174 while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) &&
175 !sequence_buffer_[index].used) {
176 ++first_seq_num_;
177 index = (index + 1) % size_;
178 }
179}
180
181bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
182 uint8_t* destination) {
183 rtc::CritScope lock(&crit_);
184
philipelf4139332016-04-20 10:26:34 +0200185 size_t index = frame.first_seq_num() % size_;
186 size_t end = (frame.last_seq_num() + 1) % size_;
187 uint16_t seq_num = frame.first_seq_num();
philipelc707ab72016-04-01 02:01:54 -0700188 while (index != end) {
189 if (!sequence_buffer_[index].used ||
190 sequence_buffer_[index].seq_num != seq_num) {
191 return false;
192 }
193
194 const uint8_t* source = data_buffer_[index].dataPtr;
195 size_t length = data_buffer_[index].sizeBytes;
196 memcpy(destination, source, length);
197 destination += length;
198 index = (index + 1) % size_;
199 ++seq_num;
200 }
201 return true;
202}
203
philipel02447bc2016-05-13 06:01:03 -0700204VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
205 rtc::CritScope lock(&crit_);
206 size_t index = seq_num % size_;
207 if (!sequence_buffer_[index].used ||
208 seq_num != sequence_buffer_[index].seq_num) {
209 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200210 }
philipel02447bc2016-05-13 06:01:03 -0700211 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200212}
213
philipel02447bc2016-05-13 06:01:03 -0700214void PacketBuffer::Clear() {
philipelc707ab72016-04-01 02:01:54 -0700215 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200216 for (size_t i = 0; i < size_; ++i)
philipelc707ab72016-04-01 02:01:54 -0700217 sequence_buffer_[i].used = false;
philipelf4139332016-04-20 10:26:34 +0200218
philipelf4139332016-04-20 10:26:34 +0200219 first_packet_received_ = false;
philipelc707ab72016-04-01 02:01:54 -0700220}
221
222} // namespace video_coding
223} // namespace webrtc