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