Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: webrtc/modules/video_coding/packet_buffer.cc

Issue 2926083002: Only create H264 frames if there are no gaps in the packet sequence number. (Closed)
Patch Set: Rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/video_coding/packet_buffer.h" 11 #include "webrtc/modules/video_coding/packet_buffer.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <limits> 14 #include <limits>
15 #include <utility> 15 #include <utility>
16 16
17 #include "webrtc/base/atomicops.h" 17 #include "webrtc/base/atomicops.h"
18 #include "webrtc/base/checks.h" 18 #include "webrtc/base/checks.h"
19 #include "webrtc/base/logging.h" 19 #include "webrtc/base/logging.h"
20 #include "webrtc/common_video/h264/h264_common.h"
20 #include "webrtc/modules/video_coding/frame_object.h" 21 #include "webrtc/modules/video_coding/frame_object.h"
21 #include "webrtc/system_wrappers/include/clock.h" 22 #include "webrtc/system_wrappers/include/clock.h"
22 23
23 namespace webrtc { 24 namespace webrtc {
24 namespace video_coding { 25 namespace video_coding {
25 26
26 rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create( 27 rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create(
27 Clock* clock, 28 Clock* clock,
28 size_t start_buffer_size, 29 size_t start_buffer_size,
29 size_t max_buffer_size, 30 size_t max_buffer_size,
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 102
102 sequence_buffer_[index].frame_begin = packet->is_first_packet_in_frame; 103 sequence_buffer_[index].frame_begin = packet->is_first_packet_in_frame;
103 sequence_buffer_[index].frame_end = packet->markerBit; 104 sequence_buffer_[index].frame_end = packet->markerBit;
104 sequence_buffer_[index].seq_num = packet->seqNum; 105 sequence_buffer_[index].seq_num = packet->seqNum;
105 sequence_buffer_[index].continuous = false; 106 sequence_buffer_[index].continuous = false;
106 sequence_buffer_[index].frame_created = false; 107 sequence_buffer_[index].frame_created = false;
107 sequence_buffer_[index].used = true; 108 sequence_buffer_[index].used = true;
108 data_buffer_[index] = *packet; 109 data_buffer_[index] = *packet;
109 packet->dataPtr = nullptr; 110 packet->dataPtr = nullptr;
110 111
112 UpdateMissingPackets(packet->seqNum);
113
111 int64_t now_ms = clock_->TimeInMilliseconds(); 114 int64_t now_ms = clock_->TimeInMilliseconds();
112 last_received_packet_ms_ = rtc::Optional<int64_t>(now_ms); 115 last_received_packet_ms_ = rtc::Optional<int64_t>(now_ms);
113 if (packet->frameType == kVideoFrameKey) 116 if (packet->frameType == kVideoFrameKey)
114 last_received_keyframe_packet_ms_ = rtc::Optional<int64_t>(now_ms); 117 last_received_keyframe_packet_ms_ = rtc::Optional<int64_t>(now_ms);
115 118
116 found_frames = FindFrames(seq_num); 119 found_frames = FindFrames(seq_num);
117 } 120 }
118 121
119 for (std::unique_ptr<RtpFrameObject>& frame : found_frames) 122 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
120 received_frame_callback_->OnReceivedFrame(std::move(frame)); 123 received_frame_callback_->OnReceivedFrame(std::move(frame));
121 124
122 return true; 125 return true;
123 } 126 }
124 127
125 void PacketBuffer::ClearTo(uint16_t seq_num) { 128 void PacketBuffer::ClearTo(uint16_t seq_num) {
126 rtc::CritScope lock(&crit_); 129 rtc::CritScope lock(&crit_);
127 130
128 // If the packet buffer was cleared between a frame was created and returned. 131 // If the packet buffer was cleared between a frame was created and returned.
129 if (!first_packet_received_) 132 if (!first_packet_received_)
130 return; 133 return;
131 134
132 is_cleared_to_first_seq_num_ = true; 135 is_cleared_to_first_seq_num_ = true;
133 while (AheadOrAt<uint16_t>(seq_num, first_seq_num_)) { 136 while (AheadOrAt<uint16_t>(seq_num, first_seq_num_)) {
134 size_t index = first_seq_num_ % size_; 137 size_t index = first_seq_num_ % size_;
135 delete[] data_buffer_[index].dataPtr; 138 delete[] data_buffer_[index].dataPtr;
136 data_buffer_[index].dataPtr = nullptr; 139 data_buffer_[index].dataPtr = nullptr;
137 sequence_buffer_[index].used = false; 140 sequence_buffer_[index].used = false;
138 ++first_seq_num_; 141 ++first_seq_num_;
139 } 142 }
143
144 missing_packets_.erase(missing_packets_.begin(),
145 missing_packets_.upper_bound(seq_num));
140 } 146 }
141 147
142 void PacketBuffer::Clear() { 148 void PacketBuffer::Clear() {
143 rtc::CritScope lock(&crit_); 149 rtc::CritScope lock(&crit_);
144 for (size_t i = 0; i < size_; ++i) { 150 for (size_t i = 0; i < size_; ++i) {
145 delete[] data_buffer_[i].dataPtr; 151 delete[] data_buffer_[i].dataPtr;
146 data_buffer_[i].dataPtr = nullptr; 152 data_buffer_[i].dataPtr = nullptr;
147 sequence_buffer_[i].used = false; 153 sequence_buffer_[i].used = false;
148 } 154 }
149 155
150 first_packet_received_ = false; 156 first_packet_received_ = false;
151 is_cleared_to_first_seq_num_ = false; 157 is_cleared_to_first_seq_num_ = false;
152 last_received_packet_ms_ = rtc::Optional<int64_t>(); 158 last_received_packet_ms_.reset();
153 last_received_keyframe_packet_ms_ = rtc::Optional<int64_t>(); 159 last_received_keyframe_packet_ms_.reset();
160 newest_inserted_seq_num_.reset();
161 missing_packets_.clear();
162 }
163
164 void PacketBuffer::PaddingReceived(uint16_t seq_num) {
165 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
166 {
167 rtc::CritScope lock(&crit_);
168 UpdateMissingPackets(seq_num);
169 found_frames = FindFrames(static_cast<uint16_t>(seq_num + 1));
170 }
171
172 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
173 received_frame_callback_->OnReceivedFrame(std::move(frame));
154 } 174 }
155 175
156 rtc::Optional<int64_t> PacketBuffer::LastReceivedPacketMs() const { 176 rtc::Optional<int64_t> PacketBuffer::LastReceivedPacketMs() const {
157 rtc::CritScope lock(&crit_); 177 rtc::CritScope lock(&crit_);
158 return last_received_packet_ms_; 178 return last_received_packet_ms_;
159 } 179 }
160 180
161 rtc::Optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const { 181 rtc::Optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const {
162 rtc::CritScope lock(&crit_); 182 rtc::CritScope lock(&crit_);
163 return last_received_keyframe_packet_ms_; 183 return last_received_keyframe_packet_ms_;
(...skipping 23 matching lines...) Expand all
187 LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size; 207 LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
188 return true; 208 return true;
189 } 209 }
190 210
191 bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const { 211 bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
192 size_t index = seq_num % size_; 212 size_t index = seq_num % size_;
193 int prev_index = index > 0 ? index - 1 : size_ - 1; 213 int prev_index = index > 0 ? index - 1 : size_ - 1;
194 214
195 if (!sequence_buffer_[index].used) 215 if (!sequence_buffer_[index].used)
196 return false; 216 return false;
217 if (sequence_buffer_[index].seq_num != seq_num)
218 return false;
197 if (sequence_buffer_[index].frame_created) 219 if (sequence_buffer_[index].frame_created)
198 return false; 220 return false;
199 if (sequence_buffer_[index].frame_begin) 221 if (sequence_buffer_[index].frame_begin)
200 return true; 222 return true;
201 if (!sequence_buffer_[prev_index].used) 223 if (!sequence_buffer_[prev_index].used)
202 return false; 224 return false;
203 if (sequence_buffer_[prev_index].frame_created) 225 if (sequence_buffer_[prev_index].frame_created)
204 return false; 226 return false;
205 if (sequence_buffer_[prev_index].seq_num != 227 if (sequence_buffer_[prev_index].seq_num !=
206 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) { 228 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
(...skipping 17 matching lines...) Expand all
224 if (sequence_buffer_[index].frame_end) { 246 if (sequence_buffer_[index].frame_end) {
225 size_t frame_size = 0; 247 size_t frame_size = 0;
226 int max_nack_count = -1; 248 int max_nack_count = -1;
227 uint16_t start_seq_num = seq_num; 249 uint16_t start_seq_num = seq_num;
228 250
229 // Find the start index by searching backward until the packet with 251 // Find the start index by searching backward until the packet with
230 // the |frame_begin| flag is set. 252 // the |frame_begin| flag is set.
231 int start_index = index; 253 int start_index = index;
232 254
233 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264; 255 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264;
256 bool is_h264_keyframe = false;
234 int64_t frame_timestamp = data_buffer_[start_index].timestamp; 257 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
235 258
236 // Since packet at |data_buffer_[index]| is already part of the frame 259 // Since packet at |data_buffer_[index]| is already part of the frame
237 // we will have at most |size_ - 1| packets left to check. 260 // we will have at most |size_ - 1| packets left to check.
238 for (size_t j = 0; j < size_ - 1; ++j) { 261 for (size_t j = 0; j < size_ - 1; ++j) {
239 frame_size += data_buffer_[start_index].sizeBytes; 262 frame_size += data_buffer_[start_index].sizeBytes;
240 max_nack_count = 263 max_nack_count =
241 std::max(max_nack_count, data_buffer_[start_index].timesNacked); 264 std::max(max_nack_count, data_buffer_[start_index].timesNacked);
242 sequence_buffer_[start_index].frame_created = true; 265 sequence_buffer_[start_index].frame_created = true;
243 266
244 if (!is_h264 && sequence_buffer_[start_index].frame_begin) 267 if (!is_h264 && sequence_buffer_[start_index].frame_begin)
245 break; 268 break;
246 269
270 if (is_h264 && !is_h264_keyframe) {
271 const RTPVideoHeaderH264& header =
272 data_buffer_[start_index].video_header.codecHeader.H264;
273 for (size_t i = 0; i < header.nalus_length; ++i) {
274 if (header.nalus[i].type == H264::NaluType::kIdr) {
275 is_h264_keyframe = true;
276 break;
277 }
278 }
279 }
280
247 start_index = start_index > 0 ? start_index - 1 : size_ - 1; 281 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
248 282
249 // In the case of H264 we don't have a frame_begin bit (yes, 283 // In the case of H264 we don't have a frame_begin bit (yes,
250 // |frame_begin| might be set to true but that is a lie). So instead 284 // |frame_begin| might be set to true but that is a lie). So instead
251 // we traverese backwards as long as we have a previous packet and 285 // we traverese backwards as long as we have a previous packet and
252 // the timestamp of that packet is the same as this one. This may cause 286 // the timestamp of that packet is the same as this one. This may cause
253 // the PacketBuffer to hand out incomplete frames. 287 // the PacketBuffer to hand out incomplete frames.
254 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106 288 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
255 if (is_h264 && 289 if (is_h264 &&
256 (!sequence_buffer_[start_index].used || 290 (!sequence_buffer_[start_index].used ||
257 data_buffer_[start_index].timestamp != frame_timestamp)) { 291 data_buffer_[start_index].timestamp != frame_timestamp)) {
258 break; 292 break;
259 } 293 }
260 294
261 --start_seq_num; 295 --start_seq_num;
262 } 296 }
263 297
298 // If this is H264 but not a keyframe, make sure there are no gaps in the
299 // packet sequence numbers up until this point.
300 if (is_h264 && !is_h264_keyframe &&
301 missing_packets_.upper_bound(start_seq_num) !=
302 missing_packets_.begin()) {
303 uint16_t stop_index = (index + 1) % size_;
304 while (start_index != stop_index) {
305 sequence_buffer_[start_index].frame_created = false;
306 start_index = (start_index + 1) % size_;
307 }
308
309 return found_frames;
310 }
311
312 missing_packets_.erase(missing_packets_.begin(),
313 missing_packets_.upper_bound(seq_num));
314
264 found_frames.emplace_back( 315 found_frames.emplace_back(
265 new RtpFrameObject(this, start_seq_num, seq_num, frame_size, 316 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
266 max_nack_count, clock_->TimeInMilliseconds())); 317 max_nack_count, clock_->TimeInMilliseconds()));
267 } 318 }
268 ++seq_num; 319 ++seq_num;
269 } 320 }
270 return found_frames; 321 return found_frames;
271 } 322 }
272 323
273 void PacketBuffer::ReturnFrame(RtpFrameObject* frame) { 324 void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 } 375 }
325 376
326 int PacketBuffer::Release() const { 377 int PacketBuffer::Release() const {
327 int count = rtc::AtomicOps::Decrement(&ref_count_); 378 int count = rtc::AtomicOps::Decrement(&ref_count_);
328 if (!count) { 379 if (!count) {
329 delete this; 380 delete this;
330 } 381 }
331 return count; 382 return count;
332 } 383 }
333 384
385 void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {
386 if (!newest_inserted_seq_num_)
387 newest_inserted_seq_num_ = rtc::Optional<uint16_t>(seq_num);
388
389 const int kMaxPaddingAge = 1000;
390 if (AheadOf(seq_num, *newest_inserted_seq_num_)) {
391 uint16_t old_seq_num = seq_num - kMaxPaddingAge;
392 auto erase_to = missing_packets_.lower_bound(old_seq_num);
393 missing_packets_.erase(missing_packets_.begin(), erase_to);
394
395 // Guard against inserting a large amount of missing packets if there is a
396 // jump in the sequence number.
397 if (AheadOf(old_seq_num, *newest_inserted_seq_num_))
398 *newest_inserted_seq_num_ = old_seq_num;
399
400 ++*newest_inserted_seq_num_;
401 while (AheadOf(seq_num, *newest_inserted_seq_num_)) {
402 missing_packets_.insert(*newest_inserted_seq_num_);
403 ++*newest_inserted_seq_num_;
404 }
405 } else {
406 missing_packets_.erase(seq_num);
407 }
408 }
409
334 } // namespace video_coding 410 } // namespace video_coding
335 } // namespace webrtc 411 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/packet_buffer.h ('k') | webrtc/modules/video_coding/video_packet_buffer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698