OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |