blob: e487f8c1db92a2443ee055ca3d75ce2431834f43 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/video_coding/packet_buffer.h"
philipelc707ab72016-04-01 02:01:54 -070012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
philipelc707ab72016-04-01 02:01:54 -070015#include <algorithm>
Yves Gerey3e707812018-11-28 16:47:49 +010016#include <cstdint>
philipel17deeb42016-08-11 15:09:26 +020017#include <utility>
philipelc707ab72016-04-01 02:01:54 -070018
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "absl/types/variant.h"
20#include "api/video/encoded_frame.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "common_video/h264/h264_common.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "modules/rtp_rtcp/source/rtp_video_header.h"
23#include "modules/video_coding/codecs/h264/include/h264_globals.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/video_coding/frame_object.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/atomic_ops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/checks.h"
27#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 16:47:49 +010028#include "rtc_base/numerics/mod_ops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "system_wrappers/include/clock.h"
Rasmus Brandt88f080a2017-11-02 14:28:06 +010030#include "system_wrappers/include/field_trial.h"
philipelc707ab72016-04-01 02:01:54 -070031
32namespace webrtc {
33namespace video_coding {
34
philipel17deeb42016-08-11 15:09:26 +020035rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create(
36 Clock* clock,
37 size_t start_buffer_size,
38 size_t max_buffer_size,
Elad Alonb4643ad2019-02-22 11:19:50 +010039 OnAssembledFrameCallback* assembled_frame_callback) {
philipel17deeb42016-08-11 15:09:26 +020040 return rtc::scoped_refptr<PacketBuffer>(new PacketBuffer(
Elad Alonb4643ad2019-02-22 11:19:50 +010041 clock, start_buffer_size, max_buffer_size, assembled_frame_callback));
philipel17deeb42016-08-11 15:09:26 +020042}
43
philipelb4d31082016-07-11 08:46:29 -070044PacketBuffer::PacketBuffer(Clock* clock,
45 size_t start_buffer_size,
philipelc707ab72016-04-01 02:01:54 -070046 size_t max_buffer_size,
Elad Alonb4643ad2019-02-22 11:19:50 +010047 OnAssembledFrameCallback* assembled_frame_callback)
philipelb4d31082016-07-11 08:46:29 -070048 : clock_(clock),
49 size_(start_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070050 max_size_(max_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070051 first_seq_num_(0),
philipelf4139332016-04-20 10:26:34 +020052 first_packet_received_(false),
philipelaee3e0e2016-11-01 11:45:34 +010053 is_cleared_to_first_seq_num_(false),
philipelc707ab72016-04-01 02:01:54 -070054 data_buffer_(start_buffer_size),
55 sequence_buffer_(start_buffer_size),
Elad Alonb4643ad2019-02-22 11:19:50 +010056 assembled_frame_callback_(assembled_frame_callback),
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +010057 unique_frames_seen_(0),
Rasmus Brandt88f080a2017-11-02 14:28:06 +010058 sps_pps_idr_is_h264_keyframe_(
59 field_trial::IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe")) {
philipelc707ab72016-04-01 02:01:54 -070060 RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
61 // Buffer size must always be a power of 2.
62 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
63 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
64}
65
philipelaee3e0e2016-11-01 11:45:34 +010066PacketBuffer::~PacketBuffer() {
67 Clear();
68}
philipel17deeb42016-08-11 15:09:26 +020069
philipel759e0b72016-11-30 01:32:05 -080070bool PacketBuffer::InsertPacket(VCMPacket* packet) {
philipelfd5a20f2016-11-15 00:57:57 -080071 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
72 {
73 rtc::CritScope lock(&crit_);
philipel3184f8e2017-05-18 08:08:53 -070074
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +010075 OnTimestampReceived(packet->timestamp);
76
philipel759e0b72016-11-30 01:32:05 -080077 uint16_t seq_num = packet->seqNum;
philipelfd5a20f2016-11-15 00:57:57 -080078 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -070079
philipelfd5a20f2016-11-15 00:57:57 -080080 if (!first_packet_received_) {
81 first_seq_num_ = seq_num;
philipelfd5a20f2016-11-15 00:57:57 -080082 first_packet_received_ = true;
83 } else if (AheadOf(first_seq_num_, seq_num)) {
84 // If we have explicitly cleared past this packet then it's old,
Johannes Kronbd3f3052019-08-01 15:45:54 +020085 // don't insert it, just silently ignore it.
philipel759e0b72016-11-30 01:32:05 -080086 if (is_cleared_to_first_seq_num_) {
87 delete[] packet->dataPtr;
88 packet->dataPtr = nullptr;
Johannes Kronbd3f3052019-08-01 15:45:54 +020089 return true;
philipel759e0b72016-11-30 01:32:05 -080090 }
philipelaee3e0e2016-11-01 11:45:34 +010091
philipelfd5a20f2016-11-15 00:57:57 -080092 first_seq_num_ = seq_num;
philipelc707ab72016-04-01 02:01:54 -070093 }
philipelc707ab72016-04-01 02:01:54 -070094
philipelfd5a20f2016-11-15 00:57:57 -080095 if (sequence_buffer_[index].used) {
philipel759e0b72016-11-30 01:32:05 -080096 // Duplicate packet, just delete the payload.
97 if (data_buffer_[index].seqNum == packet->seqNum) {
98 delete[] packet->dataPtr;
99 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800100 return true;
philipel759e0b72016-11-30 01:32:05 -0800101 }
philipelfd5a20f2016-11-15 00:57:57 -0800102
103 // The packet buffer is full, try to expand the buffer.
104 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
105 }
106 index = seq_num % size_;
107
Johannes Kronbd3f3052019-08-01 15:45:54 +0200108 // Packet buffer is still full since we were unable to expand the buffer.
philipel759e0b72016-11-30 01:32:05 -0800109 if (sequence_buffer_[index].used) {
Johannes Kronbd3f3052019-08-01 15:45:54 +0200110 // Clear the buffer, delete payload, and return false to signal that a
111 // new keyframe is needed.
112 RTC_LOG(LS_WARNING) << "Clear PacketBuffer and request key frame.";
113 Clear();
philipel759e0b72016-11-30 01:32:05 -0800114 delete[] packet->dataPtr;
115 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800116 return false;
philipel759e0b72016-11-30 01:32:05 -0800117 }
philipelfd5a20f2016-11-15 00:57:57 -0800118 }
119
Niels Möllerd5e02f02019-02-20 13:12:21 +0100120 sequence_buffer_[index].frame_begin = packet->is_first_packet_in_frame();
121 sequence_buffer_[index].frame_end = packet->is_last_packet_in_frame();
philipel759e0b72016-11-30 01:32:05 -0800122 sequence_buffer_[index].seq_num = packet->seqNum;
philipelfd5a20f2016-11-15 00:57:57 -0800123 sequence_buffer_[index].continuous = false;
124 sequence_buffer_[index].frame_created = false;
125 sequence_buffer_[index].used = true;
philipel759e0b72016-11-30 01:32:05 -0800126 data_buffer_[index] = *packet;
127 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800128
philipel2c9f9f22017-06-13 02:47:28 -0700129 UpdateMissingPackets(packet->seqNum);
130
philipel3184f8e2017-05-18 08:08:53 -0700131 int64_t now_ms = clock_->TimeInMilliseconds();
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100132 last_received_packet_ms_ = now_ms;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200133 if (packet->video_header.frame_type == VideoFrameType::kVideoFrameKey)
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100134 last_received_keyframe_packet_ms_ = now_ms;
philipel3184f8e2017-05-18 08:08:53 -0700135
philipelfd5a20f2016-11-15 00:57:57 -0800136 found_frames = FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -0700137 }
138
philipelfd5a20f2016-11-15 00:57:57 -0800139 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
Elad Alonb4643ad2019-02-22 11:19:50 +0100140 assembled_frame_callback_->OnAssembledFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700141
philipelc707ab72016-04-01 02:01:54 -0700142 return true;
143}
144
145void PacketBuffer::ClearTo(uint16_t seq_num) {
146 rtc::CritScope lock(&crit_);
philipelc5fb4682017-08-02 04:28:57 -0700147 // We have already cleared past this sequence number, no need to do anything.
148 if (is_cleared_to_first_seq_num_ &&
149 AheadOf<uint16_t>(first_seq_num_, seq_num)) {
150 return;
151 }
philipelaee3e0e2016-11-01 11:45:34 +0100152
153 // If the packet buffer was cleared between a frame was created and returned.
154 if (!first_packet_received_)
155 return;
156
philipelc5fb4682017-08-02 04:28:57 -0700157 // Avoid iterating over the buffer more than once by capping the number of
158 // iterations to the |size_| of the buffer.
159 ++seq_num;
160 size_t diff = ForwardDiff<uint16_t>(first_seq_num_, seq_num);
161 size_t iterations = std::min(diff, size_);
162 for (size_t i = 0; i < iterations; ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100163 size_t index = first_seq_num_ % size_;
philipelc5fb4682017-08-02 04:28:57 -0700164 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
165 if (AheadOf<uint16_t>(seq_num, sequence_buffer_[index].seq_num)) {
166 delete[] data_buffer_[index].dataPtr;
167 data_buffer_[index].dataPtr = nullptr;
168 sequence_buffer_[index].used = false;
169 }
philipelaee3e0e2016-11-01 11:45:34 +0100170 ++first_seq_num_;
philipelc707ab72016-04-01 02:01:54 -0700171 }
philipel2c9f9f22017-06-13 02:47:28 -0700172
philipelc5fb4682017-08-02 04:28:57 -0700173 // If |diff| is larger than |iterations| it means that we don't increment
174 // |first_seq_num_| until we reach |seq_num|, so we set it here.
175 first_seq_num_ = seq_num;
176
177 is_cleared_to_first_seq_num_ = true;
philipelbc5a4082017-12-06 10:41:08 +0100178 auto clear_to_it = missing_packets_.upper_bound(seq_num);
179 if (clear_to_it != missing_packets_.begin()) {
180 --clear_to_it;
181 missing_packets_.erase(missing_packets_.begin(), clear_to_it);
182 }
philipelc707ab72016-04-01 02:01:54 -0700183}
184
philipelaee3e0e2016-11-01 11:45:34 +0100185void PacketBuffer::Clear() {
186 rtc::CritScope lock(&crit_);
187 for (size_t i = 0; i < size_; ++i) {
188 delete[] data_buffer_[i].dataPtr;
189 data_buffer_[i].dataPtr = nullptr;
190 sequence_buffer_[i].used = false;
191 }
192
193 first_packet_received_ = false;
194 is_cleared_to_first_seq_num_ = false;
philipel2c9f9f22017-06-13 02:47:28 -0700195 last_received_packet_ms_.reset();
196 last_received_keyframe_packet_ms_.reset();
197 newest_inserted_seq_num_.reset();
198 missing_packets_.clear();
199}
200
201void PacketBuffer::PaddingReceived(uint16_t seq_num) {
202 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
203 {
204 rtc::CritScope lock(&crit_);
205 UpdateMissingPackets(seq_num);
206 found_frames = FindFrames(static_cast<uint16_t>(seq_num + 1));
207 }
208
209 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
Elad Alonb4643ad2019-02-22 11:19:50 +0100210 assembled_frame_callback_->OnAssembledFrame(std::move(frame));
philipel3184f8e2017-05-18 08:08:53 -0700211}
212
Danil Chapovalov0040b662018-06-18 10:48:16 +0200213absl::optional<int64_t> PacketBuffer::LastReceivedPacketMs() const {
philipel3184f8e2017-05-18 08:08:53 -0700214 rtc::CritScope lock(&crit_);
215 return last_received_packet_ms_;
216}
217
Danil Chapovalov0040b662018-06-18 10:48:16 +0200218absl::optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const {
philipel3184f8e2017-05-18 08:08:53 -0700219 rtc::CritScope lock(&crit_);
220 return last_received_keyframe_packet_ms_;
philipelaee3e0e2016-11-01 11:45:34 +0100221}
222
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +0100223int PacketBuffer::GetUniqueFramesSeen() const {
224 rtc::CritScope lock(&crit_);
225 return unique_frames_seen_;
226}
227
philipelc707ab72016-04-01 02:01:54 -0700228bool PacketBuffer::ExpandBufferSize() {
philipelaee3e0e2016-11-01 11:45:34 +0100229 if (size_ == max_size_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100230 RTC_LOG(LS_WARNING) << "PacketBuffer is already at max size (" << max_size_
Johannes Kronbd3f3052019-08-01 15:45:54 +0200231 << "), failed to increase size.";
philipelc707ab72016-04-01 02:01:54 -0700232 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100233 }
philipelc707ab72016-04-01 02:01:54 -0700234
235 size_t new_size = std::min(max_size_, 2 * size_);
236 std::vector<VCMPacket> new_data_buffer(new_size);
237 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
238 for (size_t i = 0; i < size_; ++i) {
239 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200240 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700241 new_sequence_buffer[index] = sequence_buffer_[i];
242 new_data_buffer[index] = data_buffer_[i];
243 }
244 }
245 size_ = new_size;
246 sequence_buffer_ = std::move(new_sequence_buffer);
247 data_buffer_ = std::move(new_data_buffer);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100248 RTC_LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
philipelc707ab72016-04-01 02:01:54 -0700249 return true;
250}
251
philipelaee3e0e2016-11-01 11:45:34 +0100252bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200253 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700254 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200255
philipelc707ab72016-04-01 02:01:54 -0700256 if (!sequence_buffer_[index].used)
257 return false;
philipel2c9f9f22017-06-13 02:47:28 -0700258 if (sequence_buffer_[index].seq_num != seq_num)
259 return false;
philipelf4139332016-04-20 10:26:34 +0200260 if (sequence_buffer_[index].frame_created)
261 return false;
philipel20dce342016-11-28 16:14:57 +0100262 if (sequence_buffer_[index].frame_begin)
philipelc707ab72016-04-01 02:01:54 -0700263 return true;
264 if (!sequence_buffer_[prev_index].used)
265 return false;
philipelea142f82017-01-11 02:01:56 -0800266 if (sequence_buffer_[prev_index].frame_created)
267 return false;
philipelf4139332016-04-20 10:26:34 +0200268 if (sequence_buffer_[prev_index].seq_num !=
philipel2c2f34c2017-01-03 05:55:34 -0800269 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
philipelf4139332016-04-20 10:26:34 +0200270 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100271 }
philipel8b6995b2019-01-09 12:39:18 +0100272 if (data_buffer_[prev_index].timestamp != data_buffer_[index].timestamp)
273 return false;
philipelc707ab72016-04-01 02:01:54 -0700274 if (sequence_buffer_[prev_index].continuous)
275 return true;
276
277 return false;
278}
279
philipelfd5a20f2016-11-15 00:57:57 -0800280std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
281 uint16_t seq_num) {
282 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
philipel53910712017-05-18 02:24:40 -0700283 for (size_t i = 0; i < size_ && PotentialNewFrame(seq_num); ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100284 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700285 sequence_buffer_[index].continuous = true;
286
philipelf4139332016-04-20 10:26:34 +0200287 // If all packets of the frame is continuous, find the first packet of the
288 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700289 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200290 size_t frame_size = 0;
291 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700292 uint16_t start_seq_num = seq_num;
Chen Xingf00bf422019-06-20 10:05:55 +0200293 int64_t min_recv_time = data_buffer_[index].packet_info.receive_time_ms();
294 int64_t max_recv_time = data_buffer_[index].packet_info.receive_time_ms();
295 RtpPacketInfos::vector_type packet_infos;
philipelf4139332016-04-20 10:26:34 +0200296
philipel5ceaaae2016-05-24 10:20:47 +0200297 // Find the start index by searching backward until the packet with
298 // the |frame_begin| flag is set.
299 int start_index = index;
philipel227f8b92017-08-04 06:39:31 -0700300 size_t tested_packets = 0;
philipel8c619242017-02-02 08:51:29 -0800301 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
philipel53910712017-05-18 02:24:40 -0700302
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100303 // Identify H.264 keyframes by means of SPS, PPS, and IDR.
Niels Möllerd5e02f02019-02-20 13:12:21 +0100304 bool is_h264 = data_buffer_[start_index].codec() == kVideoCodecH264;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100305 bool has_h264_sps = false;
306 bool has_h264_pps = false;
307 bool has_h264_idr = false;
308 bool is_h264_keyframe = false;
309
philipel227f8b92017-08-04 06:39:31 -0700310 while (true) {
311 ++tested_packets;
philipel5ceaaae2016-05-24 10:20:47 +0200312 frame_size += data_buffer_[start_index].sizeBytes;
philipelfd5a20f2016-11-15 00:57:57 -0800313 max_nack_count =
314 std::max(max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200315 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200316
Ilya Nikolaevskiy4348ce22018-12-07 16:26:56 +0100317 min_recv_time =
Chen Xingf00bf422019-06-20 10:05:55 +0200318 std::min(min_recv_time,
319 data_buffer_[start_index].packet_info.receive_time_ms());
Ilya Nikolaevskiy4348ce22018-12-07 16:26:56 +0100320 max_recv_time =
Chen Xingf00bf422019-06-20 10:05:55 +0200321 std::max(max_recv_time,
322 data_buffer_[start_index].packet_info.receive_time_ms());
323
324 // Should use |push_front()| since the loop traverses backwards. But
325 // it's too inefficient to do so on a vector so we'll instead fix the
326 // order afterwards.
327 packet_infos.push_back(data_buffer_[start_index].packet_info);
Ilya Nikolaevskiy4348ce22018-12-07 16:26:56 +0100328
philipel8c619242017-02-02 08:51:29 -0800329 if (!is_h264 && sequence_buffer_[start_index].frame_begin)
philipel5ceaaae2016-05-24 10:20:47 +0200330 break;
331
philipel2c9f9f22017-06-13 02:47:28 -0700332 if (is_h264 && !is_h264_keyframe) {
philipel7d745e52018-08-02 14:03:53 +0200333 const auto* h264_header = absl::get_if<RTPVideoHeaderH264>(
334 &data_buffer_[start_index].video_header.video_type_header);
335 if (!h264_header || h264_header->nalus_length >= kMaxNalusPerPacket)
philipel09133af2018-05-17 14:11:09 +0200336 return found_frames;
337
philipel7d745e52018-08-02 14:03:53 +0200338 for (size_t j = 0; j < h264_header->nalus_length; ++j) {
339 if (h264_header->nalus[j].type == H264::NaluType::kSps) {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100340 has_h264_sps = true;
philipel7d745e52018-08-02 14:03:53 +0200341 } else if (h264_header->nalus[j].type == H264::NaluType::kPps) {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100342 has_h264_pps = true;
philipel7d745e52018-08-02 14:03:53 +0200343 } else if (h264_header->nalus[j].type == H264::NaluType::kIdr) {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100344 has_h264_idr = true;
philipel2c9f9f22017-06-13 02:47:28 -0700345 }
346 }
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100347 if ((sps_pps_idr_is_h264_keyframe_ && has_h264_idr && has_h264_sps &&
348 has_h264_pps) ||
349 (!sps_pps_idr_is_h264_keyframe_ && has_h264_idr)) {
350 is_h264_keyframe = true;
351 }
philipel2c9f9f22017-06-13 02:47:28 -0700352 }
353
philipel227f8b92017-08-04 06:39:31 -0700354 if (tested_packets == size_)
355 break;
356
philipelf4139332016-04-20 10:26:34 +0200357 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipel8c619242017-02-02 08:51:29 -0800358
359 // In the case of H264 we don't have a frame_begin bit (yes,
360 // |frame_begin| might be set to true but that is a lie). So instead
361 // we traverese backwards as long as we have a previous packet and
362 // the timestamp of that packet is the same as this one. This may cause
363 // the PacketBuffer to hand out incomplete frames.
364 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
philipel53910712017-05-18 02:24:40 -0700365 if (is_h264 &&
philipel8c619242017-02-02 08:51:29 -0800366 (!sequence_buffer_[start_index].used ||
367 data_buffer_[start_index].timestamp != frame_timestamp)) {
368 break;
369 }
370
371 --start_seq_num;
philipelc707ab72016-04-01 02:01:54 -0700372 }
373
Chen Xingf00bf422019-06-20 10:05:55 +0200374 // Fix the order since the packet-finding loop traverses backwards.
375 std::reverse(packet_infos.begin(), packet_infos.end());
376
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100377 if (is_h264) {
378 // Warn if this is an unsafe frame.
379 if (has_h264_idr && (!has_h264_sps || !has_h264_pps)) {
Jonas Olssonfc501102018-06-15 14:24:10 +0200380 RTC_LOG(LS_WARNING)
381 << "Received H.264-IDR frame "
382 << "(SPS: " << has_h264_sps << ", PPS: " << has_h264_pps
383 << "). Treating as "
384 << (sps_pps_idr_is_h264_keyframe_ ? "delta" : "key")
385 << " frame since WebRTC-SpsPpsIdrIsH264Keyframe is "
386 << (sps_pps_idr_is_h264_keyframe_ ? "enabled." : "disabled");
philipel2c9f9f22017-06-13 02:47:28 -0700387 }
388
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100389 // Now that we have decided whether to treat this frame as a key frame
390 // or delta frame in the frame buffer, we update the field that
391 // determines if the RtpFrameObject is a key frame or delta frame.
392 const size_t first_packet_index = start_seq_num % size_;
393 RTC_CHECK_LT(first_packet_index, size_);
394 if (is_h264_keyframe) {
Niels Möllerabbc50e2019-04-24 09:41:16 +0200395 data_buffer_[first_packet_index].video_header.frame_type =
Niels Möller8f7ce222019-03-21 15:43:58 +0100396 VideoFrameType::kVideoFrameKey;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100397 } else {
Niels Möllerabbc50e2019-04-24 09:41:16 +0200398 data_buffer_[first_packet_index].video_header.frame_type =
Niels Möller8f7ce222019-03-21 15:43:58 +0100399 VideoFrameType::kVideoFrameDelta;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100400 }
401
Johnny Leebc7f41b2019-05-01 14:41:32 -0400402 // With IPPP, if this is not a keyframe, make sure there are no gaps
403 // in the packet sequence numbers up until this point.
404 const uint8_t h264tid =
405 data_buffer_[start_index].video_header.frame_marking.temporal_id;
Jonas Olssona4d87372019-07-05 19:08:33 +0200406 if (h264tid == kNoTemporalIdx && !is_h264_keyframe &&
407 missing_packets_.upper_bound(start_seq_num) !=
408 missing_packets_.begin()) {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100409 uint16_t stop_index = (index + 1) % size_;
410 while (start_index != stop_index) {
411 sequence_buffer_[start_index].frame_created = false;
412 start_index = (start_index + 1) % size_;
413 }
414
415 return found_frames;
416 }
philipel2c9f9f22017-06-13 02:47:28 -0700417 }
418
419 missing_packets_.erase(missing_packets_.begin(),
420 missing_packets_.upper_bound(seq_num));
421
philipelfd5a20f2016-11-15 00:57:57 -0800422 found_frames.emplace_back(
philipelb4d31082016-07-11 08:46:29 -0700423 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
Chen Xingf00bf422019-06-20 10:05:55 +0200424 max_nack_count, min_recv_time, max_recv_time,
425 RtpPacketInfos(std::move(packet_infos))));
philipelc707ab72016-04-01 02:01:54 -0700426 }
philipelc707ab72016-04-01 02:01:54 -0700427 ++seq_num;
428 }
philipelfd5a20f2016-11-15 00:57:57 -0800429 return found_frames;
philipelc707ab72016-04-01 02:01:54 -0700430}
431
432void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
433 rtc::CritScope lock(&crit_);
philipelf4139332016-04-20 10:26:34 +0200434 size_t index = frame->first_seq_num() % size_;
435 size_t end = (frame->last_seq_num() + 1) % size_;
436 uint16_t seq_num = frame->first_seq_num();
Johannes Kron957c62e2018-10-01 14:53:01 +0200437 uint32_t timestamp = frame->Timestamp();
philipelc707ab72016-04-01 02:01:54 -0700438 while (index != end) {
Johannes Kron957c62e2018-10-01 14:53:01 +0200439 // Check both seq_num and timestamp to handle the case when seq_num wraps
440 // around too quickly for high packet rates.
441 if (sequence_buffer_[index].seq_num == seq_num &&
442 data_buffer_[index].timestamp == timestamp) {
philipel1f39ba12016-09-21 11:27:47 +0200443 delete[] data_buffer_[index].dataPtr;
444 data_buffer_[index].dataPtr = nullptr;
philipelc707ab72016-04-01 02:01:54 -0700445 sequence_buffer_[index].used = false;
philipel1f39ba12016-09-21 11:27:47 +0200446 }
philipelf4139332016-04-20 10:26:34 +0200447
philipelc707ab72016-04-01 02:01:54 -0700448 index = (index + 1) % size_;
449 ++seq_num;
450 }
philipelc707ab72016-04-01 02:01:54 -0700451}
452
453bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
454 uint8_t* destination) {
455 rtc::CritScope lock(&crit_);
456
philipelf4139332016-04-20 10:26:34 +0200457 size_t index = frame.first_seq_num() % size_;
458 size_t end = (frame.last_seq_num() + 1) % size_;
459 uint16_t seq_num = frame.first_seq_num();
Johannes Kron957c62e2018-10-01 14:53:01 +0200460 uint32_t timestamp = frame.Timestamp();
philipel227f8b92017-08-04 06:39:31 -0700461 uint8_t* destination_end = destination + frame.size();
462
463 do {
Johannes Kron957c62e2018-10-01 14:53:01 +0200464 // Check both seq_num and timestamp to handle the case when seq_num wraps
465 // around too quickly for high packet rates.
philipelc707ab72016-04-01 02:01:54 -0700466 if (!sequence_buffer_[index].used ||
Johannes Kron957c62e2018-10-01 14:53:01 +0200467 sequence_buffer_[index].seq_num != seq_num ||
468 data_buffer_[index].timestamp != timestamp) {
philipelc707ab72016-04-01 02:01:54 -0700469 return false;
470 }
471
philipel227f8b92017-08-04 06:39:31 -0700472 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
philipelc18f1d72017-08-02 04:18:02 -0700473 size_t length = data_buffer_[index].sizeBytes;
philipel227f8b92017-08-04 06:39:31 -0700474 if (destination + length > destination_end) {
philipel0fa82a62018-03-19 15:34:53 +0100475 RTC_LOG(LS_WARNING) << "Frame (" << frame.id.picture_id << ":"
476 << static_cast<int>(frame.id.spatial_layer) << ")"
Mirko Bonadei675513b2017-11-09 11:09:25 +0100477 << " bitstream buffer is not large enough.";
philipel227f8b92017-08-04 06:39:31 -0700478 return false;
479 }
480
481 const uint8_t* source = data_buffer_[index].dataPtr;
philipelc707ab72016-04-01 02:01:54 -0700482 memcpy(destination, source, length);
483 destination += length;
484 index = (index + 1) % size_;
485 ++seq_num;
philipel227f8b92017-08-04 06:39:31 -0700486 } while (index != end);
487
philipelc707ab72016-04-01 02:01:54 -0700488 return true;
489}
490
philipel02447bc2016-05-13 06:01:03 -0700491VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
philipel02447bc2016-05-13 06:01:03 -0700492 size_t index = seq_num % size_;
493 if (!sequence_buffer_[index].used ||
494 seq_num != sequence_buffer_[index].seq_num) {
495 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200496 }
philipel02447bc2016-05-13 06:01:03 -0700497 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200498}
499
philipel17deeb42016-08-11 15:09:26 +0200500int PacketBuffer::AddRef() const {
501 return rtc::AtomicOps::Increment(&ref_count_);
502}
503
504int PacketBuffer::Release() const {
505 int count = rtc::AtomicOps::Decrement(&ref_count_);
506 if (!count) {
507 delete this;
508 }
509 return count;
510}
511
philipel2c9f9f22017-06-13 02:47:28 -0700512void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {
513 if (!newest_inserted_seq_num_)
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100514 newest_inserted_seq_num_ = seq_num;
philipel2c9f9f22017-06-13 02:47:28 -0700515
516 const int kMaxPaddingAge = 1000;
517 if (AheadOf(seq_num, *newest_inserted_seq_num_)) {
518 uint16_t old_seq_num = seq_num - kMaxPaddingAge;
519 auto erase_to = missing_packets_.lower_bound(old_seq_num);
520 missing_packets_.erase(missing_packets_.begin(), erase_to);
521
522 // Guard against inserting a large amount of missing packets if there is a
523 // jump in the sequence number.
524 if (AheadOf(old_seq_num, *newest_inserted_seq_num_))
525 *newest_inserted_seq_num_ = old_seq_num;
526
527 ++*newest_inserted_seq_num_;
528 while (AheadOf(seq_num, *newest_inserted_seq_num_)) {
529 missing_packets_.insert(*newest_inserted_seq_num_);
530 ++*newest_inserted_seq_num_;
531 }
532 } else {
533 missing_packets_.erase(seq_num);
534 }
535}
536
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +0100537void PacketBuffer::OnTimestampReceived(uint32_t rtp_timestamp) {
538 const size_t kMaxTimestampsHistory = 1000;
539 if (rtp_timestamps_history_set_.insert(rtp_timestamp).second) {
540 rtp_timestamps_history_queue_.push(rtp_timestamp);
541 ++unique_frames_seen_;
542 if (rtp_timestamps_history_set_.size() > kMaxTimestampsHistory) {
543 uint32_t discarded_timestamp = rtp_timestamps_history_queue_.front();
544 rtp_timestamps_history_set_.erase(discarded_timestamp);
545 rtp_timestamps_history_queue_.pop();
546 }
547 }
548}
549
philipelc707ab72016-04-01 02:01:54 -0700550} // namespace video_coding
551} // namespace webrtc