blob: ea38ca620aca4fa47942191d6a80a5f0bdeac7bc [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"
philipel76161f72019-09-19 11:22:22 +020021#include "api/video/encoded_image.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "common_video/h264/h264_common.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "modules/rtp_rtcp/source/rtp_video_header.h"
24#include "modules/video_coding/codecs/h264/include/h264_globals.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/video_coding/frame_object.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "rtc_base/atomic_ops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "rtc_base/checks.h"
28#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 16:47:49 +010029#include "rtc_base/numerics/mod_ops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "system_wrappers/include/clock.h"
Rasmus Brandt88f080a2017-11-02 14:28:06 +010031#include "system_wrappers/include/field_trial.h"
philipelc707ab72016-04-01 02:01:54 -070032
33namespace webrtc {
34namespace video_coding {
35
philipel17deeb42016-08-11 15:09:26 +020036rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create(
37 Clock* clock,
38 size_t start_buffer_size,
39 size_t max_buffer_size,
Elad Alonb4643ad2019-02-22 11:19:50 +010040 OnAssembledFrameCallback* assembled_frame_callback) {
philipel17deeb42016-08-11 15:09:26 +020041 return rtc::scoped_refptr<PacketBuffer>(new PacketBuffer(
Elad Alonb4643ad2019-02-22 11:19:50 +010042 clock, start_buffer_size, max_buffer_size, assembled_frame_callback));
philipel17deeb42016-08-11 15:09:26 +020043}
44
philipelb4d31082016-07-11 08:46:29 -070045PacketBuffer::PacketBuffer(Clock* clock,
46 size_t start_buffer_size,
philipelc707ab72016-04-01 02:01:54 -070047 size_t max_buffer_size,
Elad Alonb4643ad2019-02-22 11:19:50 +010048 OnAssembledFrameCallback* assembled_frame_callback)
philipelb4d31082016-07-11 08:46:29 -070049 : clock_(clock),
50 size_(start_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070051 max_size_(max_buffer_size),
philipelc707ab72016-04-01 02:01:54 -070052 first_seq_num_(0),
philipelf4139332016-04-20 10:26:34 +020053 first_packet_received_(false),
philipelaee3e0e2016-11-01 11:45:34 +010054 is_cleared_to_first_seq_num_(false),
philipelc707ab72016-04-01 02:01:54 -070055 data_buffer_(start_buffer_size),
56 sequence_buffer_(start_buffer_size),
Elad Alonb4643ad2019-02-22 11:19:50 +010057 assembled_frame_callback_(assembled_frame_callback),
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +010058 unique_frames_seen_(0),
Rasmus Brandt88f080a2017-11-02 14:28:06 +010059 sps_pps_idr_is_h264_keyframe_(
60 field_trial::IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe")) {
philipelc707ab72016-04-01 02:01:54 -070061 RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
62 // Buffer size must always be a power of 2.
63 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
64 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
65}
66
philipelaee3e0e2016-11-01 11:45:34 +010067PacketBuffer::~PacketBuffer() {
68 Clear();
69}
philipel17deeb42016-08-11 15:09:26 +020070
philipel759e0b72016-11-30 01:32:05 -080071bool PacketBuffer::InsertPacket(VCMPacket* packet) {
philipelfd5a20f2016-11-15 00:57:57 -080072 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
73 {
74 rtc::CritScope lock(&crit_);
philipel3184f8e2017-05-18 08:08:53 -070075
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +010076 OnTimestampReceived(packet->timestamp);
77
philipel759e0b72016-11-30 01:32:05 -080078 uint16_t seq_num = packet->seqNum;
philipelfd5a20f2016-11-15 00:57:57 -080079 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -070080
philipelfd5a20f2016-11-15 00:57:57 -080081 if (!first_packet_received_) {
82 first_seq_num_ = seq_num;
philipelfd5a20f2016-11-15 00:57:57 -080083 first_packet_received_ = true;
84 } else if (AheadOf(first_seq_num_, seq_num)) {
85 // If we have explicitly cleared past this packet then it's old,
Johannes Kronbd3f3052019-08-01 15:45:54 +020086 // don't insert it, just silently ignore it.
philipel759e0b72016-11-30 01:32:05 -080087 if (is_cleared_to_first_seq_num_) {
88 delete[] packet->dataPtr;
89 packet->dataPtr = nullptr;
Johannes Kronbd3f3052019-08-01 15:45:54 +020090 return true;
philipel759e0b72016-11-30 01:32:05 -080091 }
philipelaee3e0e2016-11-01 11:45:34 +010092
philipelfd5a20f2016-11-15 00:57:57 -080093 first_seq_num_ = seq_num;
philipelc707ab72016-04-01 02:01:54 -070094 }
philipelc707ab72016-04-01 02:01:54 -070095
philipelfd5a20f2016-11-15 00:57:57 -080096 if (sequence_buffer_[index].used) {
philipel759e0b72016-11-30 01:32:05 -080097 // Duplicate packet, just delete the payload.
98 if (data_buffer_[index].seqNum == packet->seqNum) {
99 delete[] packet->dataPtr;
100 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800101 return true;
philipel759e0b72016-11-30 01:32:05 -0800102 }
philipelfd5a20f2016-11-15 00:57:57 -0800103
104 // The packet buffer is full, try to expand the buffer.
105 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
106 }
107 index = seq_num % size_;
108
Johannes Kronbd3f3052019-08-01 15:45:54 +0200109 // Packet buffer is still full since we were unable to expand the buffer.
philipel759e0b72016-11-30 01:32:05 -0800110 if (sequence_buffer_[index].used) {
Johannes Kronbd3f3052019-08-01 15:45:54 +0200111 // Clear the buffer, delete payload, and return false to signal that a
112 // new keyframe is needed.
113 RTC_LOG(LS_WARNING) << "Clear PacketBuffer and request key frame.";
114 Clear();
philipel759e0b72016-11-30 01:32:05 -0800115 delete[] packet->dataPtr;
116 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800117 return false;
philipel759e0b72016-11-30 01:32:05 -0800118 }
philipelfd5a20f2016-11-15 00:57:57 -0800119 }
120
Niels Möllerd5e02f02019-02-20 13:12:21 +0100121 sequence_buffer_[index].frame_begin = packet->is_first_packet_in_frame();
122 sequence_buffer_[index].frame_end = packet->is_last_packet_in_frame();
philipel759e0b72016-11-30 01:32:05 -0800123 sequence_buffer_[index].seq_num = packet->seqNum;
philipelfd5a20f2016-11-15 00:57:57 -0800124 sequence_buffer_[index].continuous = false;
125 sequence_buffer_[index].frame_created = false;
126 sequence_buffer_[index].used = true;
philipel759e0b72016-11-30 01:32:05 -0800127 data_buffer_[index] = *packet;
128 packet->dataPtr = nullptr;
philipelfd5a20f2016-11-15 00:57:57 -0800129
philipel2c9f9f22017-06-13 02:47:28 -0700130 UpdateMissingPackets(packet->seqNum);
131
philipel3184f8e2017-05-18 08:08:53 -0700132 int64_t now_ms = clock_->TimeInMilliseconds();
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100133 last_received_packet_ms_ = now_ms;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200134 if (packet->video_header.frame_type == VideoFrameType::kVideoFrameKey)
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100135 last_received_keyframe_packet_ms_ = now_ms;
philipel3184f8e2017-05-18 08:08:53 -0700136
philipelfd5a20f2016-11-15 00:57:57 -0800137 found_frames = FindFrames(seq_num);
philipelc707ab72016-04-01 02:01:54 -0700138 }
139
philipelfd5a20f2016-11-15 00:57:57 -0800140 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
Elad Alonb4643ad2019-02-22 11:19:50 +0100141 assembled_frame_callback_->OnAssembledFrame(std::move(frame));
philipelc707ab72016-04-01 02:01:54 -0700142
philipelc707ab72016-04-01 02:01:54 -0700143 return true;
144}
145
146void PacketBuffer::ClearTo(uint16_t seq_num) {
147 rtc::CritScope lock(&crit_);
philipelc5fb4682017-08-02 04:28:57 -0700148 // We have already cleared past this sequence number, no need to do anything.
149 if (is_cleared_to_first_seq_num_ &&
150 AheadOf<uint16_t>(first_seq_num_, seq_num)) {
151 return;
152 }
philipelaee3e0e2016-11-01 11:45:34 +0100153
154 // If the packet buffer was cleared between a frame was created and returned.
155 if (!first_packet_received_)
156 return;
157
philipelc5fb4682017-08-02 04:28:57 -0700158 // Avoid iterating over the buffer more than once by capping the number of
159 // iterations to the |size_| of the buffer.
160 ++seq_num;
161 size_t diff = ForwardDiff<uint16_t>(first_seq_num_, seq_num);
162 size_t iterations = std::min(diff, size_);
163 for (size_t i = 0; i < iterations; ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100164 size_t index = first_seq_num_ % size_;
philipelc5fb4682017-08-02 04:28:57 -0700165 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
166 if (AheadOf<uint16_t>(seq_num, sequence_buffer_[index].seq_num)) {
167 delete[] data_buffer_[index].dataPtr;
168 data_buffer_[index].dataPtr = nullptr;
169 sequence_buffer_[index].used = false;
170 }
philipelaee3e0e2016-11-01 11:45:34 +0100171 ++first_seq_num_;
philipelc707ab72016-04-01 02:01:54 -0700172 }
philipel2c9f9f22017-06-13 02:47:28 -0700173
philipelc5fb4682017-08-02 04:28:57 -0700174 // If |diff| is larger than |iterations| it means that we don't increment
175 // |first_seq_num_| until we reach |seq_num|, so we set it here.
176 first_seq_num_ = seq_num;
177
178 is_cleared_to_first_seq_num_ = true;
philipelbc5a4082017-12-06 10:41:08 +0100179 auto clear_to_it = missing_packets_.upper_bound(seq_num);
180 if (clear_to_it != missing_packets_.begin()) {
181 --clear_to_it;
182 missing_packets_.erase(missing_packets_.begin(), clear_to_it);
183 }
philipelc707ab72016-04-01 02:01:54 -0700184}
185
Johannes Krona3705562019-08-26 16:37:11 +0200186void PacketBuffer::ClearInterval(uint16_t start_seq_num,
187 uint16_t stop_seq_num) {
188 size_t iterations = ForwardDiff<uint16_t>(start_seq_num, stop_seq_num + 1);
189 RTC_DCHECK_LE(iterations, size_);
190 uint16_t seq_num = start_seq_num;
191 for (size_t i = 0; i < iterations; ++i) {
192 size_t index = seq_num % size_;
193 RTC_DCHECK_EQ(sequence_buffer_[index].seq_num, seq_num);
194 RTC_DCHECK_EQ(sequence_buffer_[index].seq_num, data_buffer_[index].seqNum);
195 delete[] data_buffer_[index].dataPtr;
196 data_buffer_[index].dataPtr = nullptr;
197 sequence_buffer_[index].used = false;
198
199 ++seq_num;
200 }
201}
202
philipelaee3e0e2016-11-01 11:45:34 +0100203void PacketBuffer::Clear() {
204 rtc::CritScope lock(&crit_);
205 for (size_t i = 0; i < size_; ++i) {
206 delete[] data_buffer_[i].dataPtr;
207 data_buffer_[i].dataPtr = nullptr;
208 sequence_buffer_[i].used = false;
209 }
210
211 first_packet_received_ = false;
212 is_cleared_to_first_seq_num_ = false;
philipel2c9f9f22017-06-13 02:47:28 -0700213 last_received_packet_ms_.reset();
214 last_received_keyframe_packet_ms_.reset();
215 newest_inserted_seq_num_.reset();
216 missing_packets_.clear();
217}
218
219void PacketBuffer::PaddingReceived(uint16_t seq_num) {
220 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
221 {
222 rtc::CritScope lock(&crit_);
223 UpdateMissingPackets(seq_num);
224 found_frames = FindFrames(static_cast<uint16_t>(seq_num + 1));
225 }
226
227 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
Elad Alonb4643ad2019-02-22 11:19:50 +0100228 assembled_frame_callback_->OnAssembledFrame(std::move(frame));
philipel3184f8e2017-05-18 08:08:53 -0700229}
230
Danil Chapovalov0040b662018-06-18 10:48:16 +0200231absl::optional<int64_t> PacketBuffer::LastReceivedPacketMs() const {
philipel3184f8e2017-05-18 08:08:53 -0700232 rtc::CritScope lock(&crit_);
233 return last_received_packet_ms_;
234}
235
Danil Chapovalov0040b662018-06-18 10:48:16 +0200236absl::optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const {
philipel3184f8e2017-05-18 08:08:53 -0700237 rtc::CritScope lock(&crit_);
238 return last_received_keyframe_packet_ms_;
philipelaee3e0e2016-11-01 11:45:34 +0100239}
240
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +0100241int PacketBuffer::GetUniqueFramesSeen() const {
242 rtc::CritScope lock(&crit_);
243 return unique_frames_seen_;
244}
245
philipelc707ab72016-04-01 02:01:54 -0700246bool PacketBuffer::ExpandBufferSize() {
philipelaee3e0e2016-11-01 11:45:34 +0100247 if (size_ == max_size_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100248 RTC_LOG(LS_WARNING) << "PacketBuffer is already at max size (" << max_size_
Johannes Kronbd3f3052019-08-01 15:45:54 +0200249 << "), failed to increase size.";
philipelc707ab72016-04-01 02:01:54 -0700250 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100251 }
philipelc707ab72016-04-01 02:01:54 -0700252
253 size_t new_size = std::min(max_size_, 2 * size_);
254 std::vector<VCMPacket> new_data_buffer(new_size);
255 std::vector<ContinuityInfo> new_sequence_buffer(new_size);
256 for (size_t i = 0; i < size_; ++i) {
257 if (sequence_buffer_[i].used) {
philipelf4139332016-04-20 10:26:34 +0200258 size_t index = sequence_buffer_[i].seq_num % new_size;
philipelc707ab72016-04-01 02:01:54 -0700259 new_sequence_buffer[index] = sequence_buffer_[i];
260 new_data_buffer[index] = data_buffer_[i];
261 }
262 }
263 size_ = new_size;
264 sequence_buffer_ = std::move(new_sequence_buffer);
265 data_buffer_ = std::move(new_data_buffer);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100266 RTC_LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
philipelc707ab72016-04-01 02:01:54 -0700267 return true;
268}
269
philipelaee3e0e2016-11-01 11:45:34 +0100270bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
philipelf4139332016-04-20 10:26:34 +0200271 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700272 int prev_index = index > 0 ? index - 1 : size_ - 1;
philipelf4139332016-04-20 10:26:34 +0200273
philipelc707ab72016-04-01 02:01:54 -0700274 if (!sequence_buffer_[index].used)
275 return false;
philipel2c9f9f22017-06-13 02:47:28 -0700276 if (sequence_buffer_[index].seq_num != seq_num)
277 return false;
philipelf4139332016-04-20 10:26:34 +0200278 if (sequence_buffer_[index].frame_created)
279 return false;
philipel20dce342016-11-28 16:14:57 +0100280 if (sequence_buffer_[index].frame_begin)
philipelc707ab72016-04-01 02:01:54 -0700281 return true;
282 if (!sequence_buffer_[prev_index].used)
283 return false;
philipelea142f82017-01-11 02:01:56 -0800284 if (sequence_buffer_[prev_index].frame_created)
285 return false;
philipelf4139332016-04-20 10:26:34 +0200286 if (sequence_buffer_[prev_index].seq_num !=
philipel2c2f34c2017-01-03 05:55:34 -0800287 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
philipelf4139332016-04-20 10:26:34 +0200288 return false;
philipelaee3e0e2016-11-01 11:45:34 +0100289 }
philipel8b6995b2019-01-09 12:39:18 +0100290 if (data_buffer_[prev_index].timestamp != data_buffer_[index].timestamp)
291 return false;
philipelc707ab72016-04-01 02:01:54 -0700292 if (sequence_buffer_[prev_index].continuous)
293 return true;
294
295 return false;
296}
297
philipelfd5a20f2016-11-15 00:57:57 -0800298std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
299 uint16_t seq_num) {
300 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
philipel53910712017-05-18 02:24:40 -0700301 for (size_t i = 0; i < size_ && PotentialNewFrame(seq_num); ++i) {
philipelaee3e0e2016-11-01 11:45:34 +0100302 size_t index = seq_num % size_;
philipelc707ab72016-04-01 02:01:54 -0700303 sequence_buffer_[index].continuous = true;
304
philipelf4139332016-04-20 10:26:34 +0200305 // If all packets of the frame is continuous, find the first packet of the
306 // frame and create an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700307 if (sequence_buffer_[index].frame_end) {
philipel5ceaaae2016-05-24 10:20:47 +0200308 size_t frame_size = 0;
309 int max_nack_count = -1;
philipelc707ab72016-04-01 02:01:54 -0700310 uint16_t start_seq_num = seq_num;
Chen Xingf00bf422019-06-20 10:05:55 +0200311 int64_t min_recv_time = data_buffer_[index].packet_info.receive_time_ms();
312 int64_t max_recv_time = data_buffer_[index].packet_info.receive_time_ms();
313 RtpPacketInfos::vector_type packet_infos;
philipelf4139332016-04-20 10:26:34 +0200314
philipel5ceaaae2016-05-24 10:20:47 +0200315 // Find the start index by searching backward until the packet with
316 // the |frame_begin| flag is set.
317 int start_index = index;
philipel227f8b92017-08-04 06:39:31 -0700318 size_t tested_packets = 0;
philipel8c619242017-02-02 08:51:29 -0800319 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
philipel53910712017-05-18 02:24:40 -0700320
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100321 // Identify H.264 keyframes by means of SPS, PPS, and IDR.
Niels Möllerd5e02f02019-02-20 13:12:21 +0100322 bool is_h264 = data_buffer_[start_index].codec() == kVideoCodecH264;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100323 bool has_h264_sps = false;
324 bool has_h264_pps = false;
325 bool has_h264_idr = false;
326 bool is_h264_keyframe = false;
327
philipel227f8b92017-08-04 06:39:31 -0700328 while (true) {
329 ++tested_packets;
philipel5ceaaae2016-05-24 10:20:47 +0200330 frame_size += data_buffer_[start_index].sizeBytes;
philipelfd5a20f2016-11-15 00:57:57 -0800331 max_nack_count =
332 std::max(max_nack_count, data_buffer_[start_index].timesNacked);
philipelf4139332016-04-20 10:26:34 +0200333 sequence_buffer_[start_index].frame_created = true;
philipel5ceaaae2016-05-24 10:20:47 +0200334
Ilya Nikolaevskiy4348ce22018-12-07 16:26:56 +0100335 min_recv_time =
Chen Xingf00bf422019-06-20 10:05:55 +0200336 std::min(min_recv_time,
337 data_buffer_[start_index].packet_info.receive_time_ms());
Ilya Nikolaevskiy4348ce22018-12-07 16:26:56 +0100338 max_recv_time =
Chen Xingf00bf422019-06-20 10:05:55 +0200339 std::max(max_recv_time,
340 data_buffer_[start_index].packet_info.receive_time_ms());
341
342 // Should use |push_front()| since the loop traverses backwards. But
343 // it's too inefficient to do so on a vector so we'll instead fix the
344 // order afterwards.
345 packet_infos.push_back(data_buffer_[start_index].packet_info);
Ilya Nikolaevskiy4348ce22018-12-07 16:26:56 +0100346
philipel8c619242017-02-02 08:51:29 -0800347 if (!is_h264 && sequence_buffer_[start_index].frame_begin)
philipel5ceaaae2016-05-24 10:20:47 +0200348 break;
349
philipel2c9f9f22017-06-13 02:47:28 -0700350 if (is_h264 && !is_h264_keyframe) {
philipel7d745e52018-08-02 14:03:53 +0200351 const auto* h264_header = absl::get_if<RTPVideoHeaderH264>(
352 &data_buffer_[start_index].video_header.video_type_header);
353 if (!h264_header || h264_header->nalus_length >= kMaxNalusPerPacket)
philipel09133af2018-05-17 14:11:09 +0200354 return found_frames;
355
philipel7d745e52018-08-02 14:03:53 +0200356 for (size_t j = 0; j < h264_header->nalus_length; ++j) {
357 if (h264_header->nalus[j].type == H264::NaluType::kSps) {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100358 has_h264_sps = true;
philipel7d745e52018-08-02 14:03:53 +0200359 } else if (h264_header->nalus[j].type == H264::NaluType::kPps) {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100360 has_h264_pps = true;
philipel7d745e52018-08-02 14:03:53 +0200361 } else if (h264_header->nalus[j].type == H264::NaluType::kIdr) {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100362 has_h264_idr = true;
philipel2c9f9f22017-06-13 02:47:28 -0700363 }
364 }
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100365 if ((sps_pps_idr_is_h264_keyframe_ && has_h264_idr && has_h264_sps &&
366 has_h264_pps) ||
367 (!sps_pps_idr_is_h264_keyframe_ && has_h264_idr)) {
368 is_h264_keyframe = true;
369 }
philipel2c9f9f22017-06-13 02:47:28 -0700370 }
371
philipel227f8b92017-08-04 06:39:31 -0700372 if (tested_packets == size_)
373 break;
374
philipelf4139332016-04-20 10:26:34 +0200375 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
philipel8c619242017-02-02 08:51:29 -0800376
377 // In the case of H264 we don't have a frame_begin bit (yes,
378 // |frame_begin| might be set to true but that is a lie). So instead
379 // we traverese backwards as long as we have a previous packet and
380 // the timestamp of that packet is the same as this one. This may cause
381 // the PacketBuffer to hand out incomplete frames.
382 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
philipel53910712017-05-18 02:24:40 -0700383 if (is_h264 &&
philipel8c619242017-02-02 08:51:29 -0800384 (!sequence_buffer_[start_index].used ||
385 data_buffer_[start_index].timestamp != frame_timestamp)) {
386 break;
387 }
388
389 --start_seq_num;
philipelc707ab72016-04-01 02:01:54 -0700390 }
391
Chen Xingf00bf422019-06-20 10:05:55 +0200392 // Fix the order since the packet-finding loop traverses backwards.
393 std::reverse(packet_infos.begin(), packet_infos.end());
394
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100395 if (is_h264) {
396 // Warn if this is an unsafe frame.
397 if (has_h264_idr && (!has_h264_sps || !has_h264_pps)) {
Jonas Olssonfc501102018-06-15 14:24:10 +0200398 RTC_LOG(LS_WARNING)
399 << "Received H.264-IDR frame "
400 << "(SPS: " << has_h264_sps << ", PPS: " << has_h264_pps
401 << "). Treating as "
402 << (sps_pps_idr_is_h264_keyframe_ ? "delta" : "key")
403 << " frame since WebRTC-SpsPpsIdrIsH264Keyframe is "
404 << (sps_pps_idr_is_h264_keyframe_ ? "enabled." : "disabled");
philipel2c9f9f22017-06-13 02:47:28 -0700405 }
406
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100407 // Now that we have decided whether to treat this frame as a key frame
408 // or delta frame in the frame buffer, we update the field that
409 // determines if the RtpFrameObject is a key frame or delta frame.
410 const size_t first_packet_index = start_seq_num % size_;
411 RTC_CHECK_LT(first_packet_index, size_);
412 if (is_h264_keyframe) {
Niels Möllerabbc50e2019-04-24 09:41:16 +0200413 data_buffer_[first_packet_index].video_header.frame_type =
Niels Möller8f7ce222019-03-21 15:43:58 +0100414 VideoFrameType::kVideoFrameKey;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100415 } else {
Niels Möllerabbc50e2019-04-24 09:41:16 +0200416 data_buffer_[first_packet_index].video_header.frame_type =
Niels Möller8f7ce222019-03-21 15:43:58 +0100417 VideoFrameType::kVideoFrameDelta;
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100418 }
419
Johnny Leebc7f41b2019-05-01 14:41:32 -0400420 // With IPPP, if this is not a keyframe, make sure there are no gaps
421 // in the packet sequence numbers up until this point.
422 const uint8_t h264tid =
423 data_buffer_[start_index].video_header.frame_marking.temporal_id;
Jonas Olssona4d87372019-07-05 19:08:33 +0200424 if (h264tid == kNoTemporalIdx && !is_h264_keyframe &&
425 missing_packets_.upper_bound(start_seq_num) !=
426 missing_packets_.begin()) {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100427 uint16_t stop_index = (index + 1) % size_;
428 while (start_index != stop_index) {
429 sequence_buffer_[start_index].frame_created = false;
430 start_index = (start_index + 1) % size_;
431 }
432
433 return found_frames;
434 }
philipel2c9f9f22017-06-13 02:47:28 -0700435 }
436
437 missing_packets_.erase(missing_packets_.begin(),
438 missing_packets_.upper_bound(seq_num));
439
philipel76161f72019-09-19 11:22:22 +0200440 auto frame = std::make_unique<RtpFrameObject>(
441 this, start_seq_num, seq_num, frame_size, max_nack_count,
442 min_recv_time, max_recv_time,
443 RtpPacketInfos(std::move(packet_infos)));
444 frame->SetEncodedData(EncodedImageBuffer::Create(frame_size));
445 GetBitstream(*frame, frame->data());
446 found_frames.emplace_back(std::move(frame));
447
Johannes Krona3705562019-08-26 16:37:11 +0200448 ClearInterval(start_seq_num, seq_num);
philipelc707ab72016-04-01 02:01:54 -0700449 }
philipelc707ab72016-04-01 02:01:54 -0700450 ++seq_num;
451 }
philipelfd5a20f2016-11-15 00:57:57 -0800452 return found_frames;
philipelc707ab72016-04-01 02:01:54 -0700453}
454
philipel76161f72019-09-19 11:22:22 +0200455// TODO(philipel): Update function to not accept an RtpFrameObject.
philipelc707ab72016-04-01 02:01:54 -0700456bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
457 uint8_t* destination) {
458 rtc::CritScope lock(&crit_);
459
philipelf4139332016-04-20 10:26:34 +0200460 size_t index = frame.first_seq_num() % size_;
461 size_t end = (frame.last_seq_num() + 1) % size_;
462 uint16_t seq_num = frame.first_seq_num();
Johannes Kron957c62e2018-10-01 14:53:01 +0200463 uint32_t timestamp = frame.Timestamp();
philipel227f8b92017-08-04 06:39:31 -0700464 uint8_t* destination_end = destination + frame.size();
465
466 do {
Johannes Kron957c62e2018-10-01 14:53:01 +0200467 // Check both seq_num and timestamp to handle the case when seq_num wraps
468 // around too quickly for high packet rates.
philipelc707ab72016-04-01 02:01:54 -0700469 if (!sequence_buffer_[index].used ||
Johannes Kron957c62e2018-10-01 14:53:01 +0200470 sequence_buffer_[index].seq_num != seq_num ||
471 data_buffer_[index].timestamp != timestamp) {
philipelc707ab72016-04-01 02:01:54 -0700472 return false;
473 }
474
philipel227f8b92017-08-04 06:39:31 -0700475 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
philipelc18f1d72017-08-02 04:18:02 -0700476 size_t length = data_buffer_[index].sizeBytes;
philipel227f8b92017-08-04 06:39:31 -0700477 if (destination + length > destination_end) {
philipel0fa82a62018-03-19 15:34:53 +0100478 RTC_LOG(LS_WARNING) << "Frame (" << frame.id.picture_id << ":"
479 << static_cast<int>(frame.id.spatial_layer) << ")"
Mirko Bonadei675513b2017-11-09 11:09:25 +0100480 << " bitstream buffer is not large enough.";
philipel227f8b92017-08-04 06:39:31 -0700481 return false;
482 }
483
484 const uint8_t* source = data_buffer_[index].dataPtr;
philipelc707ab72016-04-01 02:01:54 -0700485 memcpy(destination, source, length);
486 destination += length;
487 index = (index + 1) % size_;
488 ++seq_num;
philipel227f8b92017-08-04 06:39:31 -0700489 } while (index != end);
490
philipelc707ab72016-04-01 02:01:54 -0700491 return true;
492}
493
philipel02447bc2016-05-13 06:01:03 -0700494VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
philipel02447bc2016-05-13 06:01:03 -0700495 size_t index = seq_num % size_;
496 if (!sequence_buffer_[index].used ||
497 seq_num != sequence_buffer_[index].seq_num) {
498 return nullptr;
philipelf4139332016-04-20 10:26:34 +0200499 }
philipel02447bc2016-05-13 06:01:03 -0700500 return &data_buffer_[index];
philipelf4139332016-04-20 10:26:34 +0200501}
502
philipel17deeb42016-08-11 15:09:26 +0200503int PacketBuffer::AddRef() const {
504 return rtc::AtomicOps::Increment(&ref_count_);
505}
506
507int PacketBuffer::Release() const {
508 int count = rtc::AtomicOps::Decrement(&ref_count_);
509 if (!count) {
510 delete this;
511 }
512 return count;
513}
514
philipel2c9f9f22017-06-13 02:47:28 -0700515void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {
516 if (!newest_inserted_seq_num_)
Oskar Sundbom6bd39022017-11-16 10:54:49 +0100517 newest_inserted_seq_num_ = seq_num;
philipel2c9f9f22017-06-13 02:47:28 -0700518
519 const int kMaxPaddingAge = 1000;
520 if (AheadOf(seq_num, *newest_inserted_seq_num_)) {
521 uint16_t old_seq_num = seq_num - kMaxPaddingAge;
522 auto erase_to = missing_packets_.lower_bound(old_seq_num);
523 missing_packets_.erase(missing_packets_.begin(), erase_to);
524
525 // Guard against inserting a large amount of missing packets if there is a
526 // jump in the sequence number.
527 if (AheadOf(old_seq_num, *newest_inserted_seq_num_))
528 *newest_inserted_seq_num_ = old_seq_num;
529
530 ++*newest_inserted_seq_num_;
531 while (AheadOf(seq_num, *newest_inserted_seq_num_)) {
532 missing_packets_.insert(*newest_inserted_seq_num_);
533 ++*newest_inserted_seq_num_;
534 }
535 } else {
536 missing_packets_.erase(seq_num);
537 }
538}
539
Ilya Nikolaevskiyd397a0d2018-02-21 15:57:09 +0100540void PacketBuffer::OnTimestampReceived(uint32_t rtp_timestamp) {
541 const size_t kMaxTimestampsHistory = 1000;
542 if (rtp_timestamps_history_set_.insert(rtp_timestamp).second) {
543 rtp_timestamps_history_queue_.push(rtp_timestamp);
544 ++unique_frames_seen_;
545 if (rtp_timestamps_history_set_.size() > kMaxTimestampsHistory) {
546 uint32_t discarded_timestamp = rtp_timestamps_history_queue_.front();
547 rtp_timestamps_history_set_.erase(discarded_timestamp);
548 rtp_timestamps_history_queue_.pop();
549 }
550 }
551}
552
philipelc707ab72016-04-01 02:01:54 -0700553} // namespace video_coding
554} // namespace webrtc