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

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

Issue 2989313003: Reland of Fix off-by-one bugs in PacketBuffer when the buffer is filled with a single frame. (Closed)
Patch Set: Memcpy fix Created 3 years, 4 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
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 // If all packets of the frame is continuous, find the first packet of the 261 // If all packets of the frame is continuous, find the first packet of the
262 // frame and create an RtpFrameObject. 262 // frame and create an RtpFrameObject.
263 if (sequence_buffer_[index].frame_end) { 263 if (sequence_buffer_[index].frame_end) {
264 size_t frame_size = 0; 264 size_t frame_size = 0;
265 int max_nack_count = -1; 265 int max_nack_count = -1;
266 uint16_t start_seq_num = seq_num; 266 uint16_t start_seq_num = seq_num;
267 267
268 // Find the start index by searching backward until the packet with 268 // Find the start index by searching backward until the packet with
269 // the |frame_begin| flag is set. 269 // the |frame_begin| flag is set.
270 int start_index = index; 270 int start_index = index;
271 size_t tested_packets = 0;
271 272
272 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264; 273 bool is_h264 = data_buffer_[start_index].codec == kVideoCodecH264;
273 bool is_h264_keyframe = false; 274 bool is_h264_keyframe = false;
274 int64_t frame_timestamp = data_buffer_[start_index].timestamp; 275 int64_t frame_timestamp = data_buffer_[start_index].timestamp;
275 276
276 // Since packet at |data_buffer_[index]| is already part of the frame 277 while (true) {
277 // we will have at most |size_ - 1| packets left to check. 278 ++tested_packets;
278 for (size_t j = 0; j < size_ - 1; ++j) {
279 frame_size += data_buffer_[start_index].sizeBytes; 279 frame_size += data_buffer_[start_index].sizeBytes;
280 max_nack_count = 280 max_nack_count =
281 std::max(max_nack_count, data_buffer_[start_index].timesNacked); 281 std::max(max_nack_count, data_buffer_[start_index].timesNacked);
282 sequence_buffer_[start_index].frame_created = true; 282 sequence_buffer_[start_index].frame_created = true;
283 283
284 if (!is_h264 && sequence_buffer_[start_index].frame_begin) 284 if (!is_h264 && sequence_buffer_[start_index].frame_begin)
285 break; 285 break;
286 286
287 if (is_h264 && !is_h264_keyframe) { 287 if (is_h264 && !is_h264_keyframe) {
288 const RTPVideoHeaderH264& header = 288 const RTPVideoHeaderH264& header =
289 data_buffer_[start_index].video_header.codecHeader.H264; 289 data_buffer_[start_index].video_header.codecHeader.H264;
290 for (size_t i = 0; i < header.nalus_length; ++i) { 290 for (size_t i = 0; i < header.nalus_length; ++i) {
291 if (header.nalus[i].type == H264::NaluType::kIdr) { 291 if (header.nalus[i].type == H264::NaluType::kIdr) {
292 is_h264_keyframe = true; 292 is_h264_keyframe = true;
293 break; 293 break;
294 } 294 }
295 } 295 }
296 } 296 }
297 297
298 if (tested_packets == size_)
299 break;
300
298 start_index = start_index > 0 ? start_index - 1 : size_ - 1; 301 start_index = start_index > 0 ? start_index - 1 : size_ - 1;
299 302
300 // In the case of H264 we don't have a frame_begin bit (yes, 303 // In the case of H264 we don't have a frame_begin bit (yes,
301 // |frame_begin| might be set to true but that is a lie). So instead 304 // |frame_begin| might be set to true but that is a lie). So instead
302 // we traverese backwards as long as we have a previous packet and 305 // we traverese backwards as long as we have a previous packet and
303 // the timestamp of that packet is the same as this one. This may cause 306 // the timestamp of that packet is the same as this one. This may cause
304 // the PacketBuffer to hand out incomplete frames. 307 // the PacketBuffer to hand out incomplete frames.
305 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106 308 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7106
306 if (is_h264 && 309 if (is_h264 &&
307 (!sequence_buffer_[start_index].used || 310 (!sequence_buffer_[start_index].used ||
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 } 358 }
356 } 359 }
357 360
358 bool PacketBuffer::GetBitstream(const RtpFrameObject& frame, 361 bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
359 uint8_t* destination) { 362 uint8_t* destination) {
360 rtc::CritScope lock(&crit_); 363 rtc::CritScope lock(&crit_);
361 364
362 size_t index = frame.first_seq_num() % size_; 365 size_t index = frame.first_seq_num() % size_;
363 size_t end = (frame.last_seq_num() + 1) % size_; 366 size_t end = (frame.last_seq_num() + 1) % size_;
364 uint16_t seq_num = frame.first_seq_num(); 367 uint16_t seq_num = frame.first_seq_num();
365 while (index != end) { 368 uint8_t* destination_end = destination + frame.size();
369
370 do {
366 if (!sequence_buffer_[index].used || 371 if (!sequence_buffer_[index].used ||
367 sequence_buffer_[index].seq_num != seq_num) { 372 sequence_buffer_[index].seq_num != seq_num) {
368 return false; 373 return false;
369 } 374 }
370 375
376 RTC_DCHECK_EQ(data_buffer_[index].seqNum, sequence_buffer_[index].seq_num);
377 size_t length = data_buffer_[index].sizeBytes;
378 if (destination + length > destination_end) {
379 LOG(LS_WARNING) << "Frame (" << frame.picture_id << ":"
380 << static_cast<int>(frame.spatial_layer) << ")"
381 << " bitstream buffer is not large enough.";
382 return false;
383 }
384
371 const uint8_t* source = data_buffer_[index].dataPtr; 385 const uint8_t* source = data_buffer_[index].dataPtr;
372 size_t length = data_buffer_[index].sizeBytes;
373 memcpy(destination, source, length); 386 memcpy(destination, source, length);
374 destination += length; 387 destination += length;
375 index = (index + 1) % size_; 388 index = (index + 1) % size_;
376 ++seq_num; 389 ++seq_num;
377 } 390 } while (index != end);
391
378 return true; 392 return true;
379 } 393 }
380 394
381 VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) { 395 VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
382 size_t index = seq_num % size_; 396 size_t index = seq_num % size_;
383 if (!sequence_buffer_[index].used || 397 if (!sequence_buffer_[index].used ||
384 seq_num != sequence_buffer_[index].seq_num) { 398 seq_num != sequence_buffer_[index].seq_num) {
385 return nullptr; 399 return nullptr;
386 } 400 }
387 return &data_buffer_[index]; 401 return &data_buffer_[index];
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 missing_packets_.insert(*newest_inserted_seq_num_); 433 missing_packets_.insert(*newest_inserted_seq_num_);
420 ++*newest_inserted_seq_num_; 434 ++*newest_inserted_seq_num_;
421 } 435 }
422 } else { 436 } else {
423 missing_packets_.erase(seq_num); 437 missing_packets_.erase(seq_num);
424 } 438 }
425 } 439 }
426 440
427 } // namespace video_coding 441 } // namespace video_coding
428 } // namespace webrtc 442 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/frame_object.cc ('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