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

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: 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_ = rtc::Optional<int64_t>();
153 last_received_keyframe_packet_ms_ = rtc::Optional<int64_t>(); 159 last_received_keyframe_packet_ms_ = rtc::Optional<int64_t>();
160 missing_packets_.clear();
161 }
162
163 void PacketBuffer::PaddingReceived(uint16_t seq_num) {
164 std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
165 {
166 rtc::CritScope lock(&crit_);
167 UpdateMissingPackets(seq_num);
168 found_frames = FindFrames(static_cast<uint16_t>(seq_num + 1));
169 }
170
171 for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
172 received_frame_callback_->OnReceivedFrame(std::move(frame));
154 } 173 }
155 174
156 rtc::Optional<int64_t> PacketBuffer::LastReceivedPacketMs() const { 175 rtc::Optional<int64_t> PacketBuffer::LastReceivedPacketMs() const {
157 rtc::CritScope lock(&crit_); 176 rtc::CritScope lock(&crit_);
158 return last_received_packet_ms_; 177 return last_received_packet_ms_;
159 } 178 }
160 179
161 rtc::Optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const { 180 rtc::Optional<int64_t> PacketBuffer::LastReceivedKeyframePacketMs() const {
162 rtc::CritScope lock(&crit_); 181 rtc::CritScope lock(&crit_);
163 return last_received_keyframe_packet_ms_; 182 return last_received_keyframe_packet_ms_;
(...skipping 23 matching lines...) Expand all
187 LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size; 206 LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
188 return true; 207 return true;
189 } 208 }
190 209
191 bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const { 210 bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
192 size_t index = seq_num % size_; 211 size_t index = seq_num % size_;
193 int prev_index = index > 0 ? index - 1 : size_ - 1; 212 int prev_index = index > 0 ? index - 1 : size_ - 1;
194 213
195 if (!sequence_buffer_[index].used) 214 if (!sequence_buffer_[index].used)
196 return false; 215 return false;
216 if (sequence_buffer_[index].seq_num != seq_num)
stefan-webrtc 2017/06/07 11:39:16 Not sure I follow this. If the sequence number rec
philipel 2017/06/07 14:04:34 The problem we have now is that we can have receiv
217 return false;
197 if (sequence_buffer_[index].frame_created) 218 if (sequence_buffer_[index].frame_created)
198 return false; 219 return false;
199 if (sequence_buffer_[index].frame_begin) 220 if (sequence_buffer_[index].frame_begin)
200 return true; 221 return true;
201 if (!sequence_buffer_[prev_index].used) 222 if (!sequence_buffer_[prev_index].used)
202 return false; 223 return false;
203 if (sequence_buffer_[prev_index].frame_created) 224 if (sequence_buffer_[prev_index].frame_created)
204 return false; 225 return false;
205 if (sequence_buffer_[prev_index].seq_num != 226 if (sequence_buffer_[prev_index].seq_num !=
206 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) { 227 static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
(...skipping 17 matching lines...) Expand all
224 if (sequence_buffer_[index].frame_end) { 245 if (sequence_buffer_[index].frame_end) {
225 size_t frame_size = 0; 246 size_t frame_size = 0;
226 int max_nack_count = -1; 247 int max_nack_count = -1;
227 uint16_t start_seq_num = seq_num; 248 uint16_t start_seq_num = seq_num;
228 249
229 // Find the start index by searching backward until the packet with 250 // Find the start index by searching backward until the packet with
230 // the |frame_begin| flag is set. 251 // the |frame_begin| flag is set.
231 int start_index = index; 252 int start_index = index;
232 253
233 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264; 254 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264;
255 bool is_h264_keyframe = false;
234 int64_t frame_timestamp = data_buffer_[start_index].timestamp; 256 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
235 257
236 // Since packet at |data_buffer_[index]| is already part of the frame 258 // Since packet at |data_buffer_[index]| is already part of the frame
237 // we will have at most |size_ - 1| packets left to check. 259 // we will have at most |size_ - 1| packets left to check.
238 for (size_t j = 0; j < size_ - 1; ++j) { 260 for (size_t j = 0; j < size_ - 1; ++j) {
239 frame_size += data_buffer_[start_index].sizeBytes; 261 frame_size += data_buffer_[start_index].sizeBytes;
240 max_nack_count = 262 max_nack_count =
241 std::max(max_nack_count, data_buffer_[start_index].timesNacked); 263 std::max(max_nack_count, data_buffer_[start_index].timesNacked);
242 sequence_buffer_[start_index].frame_created = true; 264 sequence_buffer_[start_index].frame_created = true;
243 265
244 if (!is_h264 && sequence_buffer_[start_index].frame_begin) 266 if (!is_h264 && sequence_buffer_[start_index].frame_begin)
245 break; 267 break;
246 268
269 if (is_h264 && !is_h264_keyframe) {
270 const RTPVideoHeaderH264& header =
271 data_buffer_[start_index].video_header.codecHeader.H264;
272 for (size_t i = 0; i < header.nalus_length; ++i) {
273 if (header.nalus[i].type == H264::NaluType::kIdr) {
274 is_h264_keyframe = true;
275 break;
276 }
277 }
278 }
279
247 start_index = start_index > 0 ? start_index - 1 : size_ - 1; 280 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
248 281
249 // In the case of H264 we don't have a frame_begin bit (yes, 282 // 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 283 // |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 284 // 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 285 // the timestamp of that packet is the same as this one. This may cause
253 // the PacketBuffer to hand out incomplete frames. 286 // the PacketBuffer to hand out incomplete frames.
254 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106 287 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
255 if (is_h264 && 288 if (is_h264 &&
256 (!sequence_buffer_[start_index].used || 289 (!sequence_buffer_[start_index].used ||
257 data_buffer_[start_index].timestamp != frame_timestamp)) { 290 data_buffer_[start_index].timestamp != frame_timestamp)) {
258 break; 291 break;
259 } 292 }
260 293
261 --start_seq_num; 294 --start_seq_num;
262 } 295 }
263 296
297 // If this is H264 but not a keyframe, make sure there are no gaps in the
298 // packet sequence numbers up until this point.
299 if (is_h264 && !is_h264_keyframe &&
300 missing_packets_.upper_bound(start_seq_num) !=
301 missing_packets_.begin()) {
302 uint16_t stop_index = (index + 1) % size_;
303 while (start_index != stop_index) {
304 sequence_buffer_[start_index].frame_created = false;
305 start_index = (start_index + 1) % size_;
306 }
307
308 return found_frames;
309 }
310
311 // Clearing missing packets this way can cause H264 frames older than
312 // the last keyframe to be considered received.
stefan-webrtc 2017/06/07 11:39:17 What does this imply? Are those packets even inter
philipel 2017/06/07 14:04:35 I don't understand my own comment :) What I wante
stefan-webrtc 2017/06/12 08:56:21 Is this a better comment? // Frames prior to this
313 missing_packets_.erase(missing_packets_.begin(),
314 missing_packets_.upper_bound(seq_num));
315
264 found_frames.emplace_back( 316 found_frames.emplace_back(
265 new RtpFrameObject(this, start_seq_num, seq_num, frame_size, 317 new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
266 max_nack_count, clock_->TimeInMilliseconds())); 318 max_nack_count, clock_->TimeInMilliseconds()));
267 } 319 }
268 ++seq_num; 320 ++seq_num;
269 } 321 }
270 return found_frames; 322 return found_frames;
271 } 323 }
272 324
273 void PacketBuffer::ReturnFrame(RtpFrameObject* frame) { 325 void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 } 376 }
325 377
326 int PacketBuffer::Release() const { 378 int PacketBuffer::Release() const {
327 int count = rtc::AtomicOps::Decrement(&ref_count_); 379 int count = rtc::AtomicOps::Decrement(&ref_count_);
328 if (!count) { 380 if (!count) {
329 delete this; 381 delete this;
330 } 382 }
331 return count; 383 return count;
332 } 384 }
333 385
386 void PacketBuffer::UpdateMissingPackets(uint16_t seq_num) {
387 if (!last_inserted_seq_num_)
388 last_inserted_seq_num_ = rtc::Optional<uint16_t>(seq_num);
389
390 const int kMaxPaddingAge = 1000;
391 if (AheadOf(seq_num, *last_inserted_seq_num_)) {
392 auto erase_to =
393 missing_packets_.lower_bound(*last_inserted_seq_num_ - kMaxPaddingAge);
394 missing_packets_.erase(missing_packets_.begin(), erase_to);
395
396 ++*last_inserted_seq_num_;
397 while (AheadOf(seq_num, *last_inserted_seq_num_)) {
398 missing_packets_.insert(*last_inserted_seq_num_);
stefan-webrtc 2017/06/07 11:39:16 Should we guard for not inserting 65000 sequence n
philipel 2017/06/07 14:04:35 We can insert at most 2^15 missing packets, otherw
399 ++*last_inserted_seq_num_;
400 }
401 } else {
402 missing_packets_.erase(seq_num);
403 }
404 }
405
334 } // namespace video_coding 406 } // namespace video_coding
335 } // namespace webrtc 407 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698