In PacketBuffer use helper to find packet slot in the buffer This is a preparation for using unwrapped int64_t instead of wrapped uint16_t RTP sequence number in PacketBuffer. Using modular works when sequence number is unsigned but produces incorrect result when signed sequence number happens to be negative. Bug: chromium:537233963 Change-Id: I515cb7441d052a2823eee4891bb4e17b254d602f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/491920 Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Cr-Commit-Position: refs/heads/main@{#48231}
diff --git a/modules/video_coding/packet_buffer.cc b/modules/video_coding/packet_buffer.cc index 0efaa87..815e0f4 100644 --- a/modules/video_coding/packet_buffer.cc +++ b/modules/video_coding/packet_buffer.cc
@@ -68,7 +68,7 @@ PacketBuffer::InsertResult result; uint16_t seq_num = packet->seq_num(); - size_t index = seq_num % buffer_.size(); + size_t index = Index(seq_num); if (!first_packet_received_) { first_seq_num_ = seq_num; @@ -98,9 +98,11 @@ } // The packet buffer is full, try to expand the buffer. - while (ExpandBufferSize() && buffer_[seq_num % buffer_.size()] != nullptr) { + // Note that `ExpandBufferSize` changes `buffer_.size()` and thus `Index` + // has to be recalculated after it. + while (ExpandBufferSize() && buffer_[Index(seq_num)] != nullptr) { } - index = seq_num % buffer_.size(); + index = Index(seq_num); // Packet buffer is still full since we were unable to expand the buffer. if (buffer_[index] != nullptr) { @@ -142,7 +144,7 @@ size_t diff = ForwardDiff<uint16_t>(first_seq_num_, seq_num); size_t iterations = std::min(diff, buffer_.size()); for (size_t i = 0; i < iterations; ++i) { - auto& stored = buffer_[first_seq_num_ % buffer_.size()]; + auto& stored = buffer_[Index(first_seq_num_)]; if (stored != nullptr && AheadOf<uint16_t>(seq_num, stored->seq_num())) { stored = nullptr; } @@ -204,7 +206,7 @@ std::vector<std::unique_ptr<Packet>> new_buffer(new_size); for (std::unique_ptr<Packet>& entry : buffer_) { if (entry != nullptr) { - new_buffer[entry->seq_num() % new_size] = std::move(entry); + new_buffer[Index(entry->seq_num(), new_size)] = std::move(entry); } } buffer_ = std::move(new_buffer); @@ -213,10 +215,8 @@ } bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const { - size_t index = seq_num % buffer_.size(); - int prev_index = index > 0 ? index - 1 : buffer_.size() - 1; - const auto& entry = buffer_[index]; - const auto& prev_entry = buffer_[prev_index]; + const auto& entry = buffer_[Index(seq_num)]; + const auto& prev_entry = buffer_[Index(seq_num - 1)]; if (entry == nullptr) return false; @@ -251,7 +251,7 @@ break; } - size_t index = seq_num % buffer_.size(); + size_t index = Index(seq_num); buffer_[index]->continuous = true; // If all packets of the frame is continuous, find the first packet of the @@ -363,7 +363,7 @@ // Now that we have decided whether to treat this frame as a key frame // or delta frame in the frame buffer, we update the field that // determines if the RtpFrameObject is a key frame or delta frame. - const size_t first_packet_index = start_seq_num % buffer_.size(); + const size_t first_packet_index = Index(start_seq_num); if (is_h264_keyframe) { buffer_[first_packet_index]->video_header.frame_type = VideoFrameType::kVideoFrameKey; @@ -392,7 +392,7 @@ uint16_t num_packets = end_seq_num - start_seq_num; found_frames.reserve(found_frames.size() + num_packets); for (uint16_t j = start_seq_num; j != end_seq_num; ++j) { - std::unique_ptr<Packet>& packet = buffer_[j % buffer_.size()]; + std::unique_ptr<Packet>& packet = buffer_[Index(j)]; RTC_DCHECK(packet); RTC_DCHECK_EQ(j, packet->seq_num()); // Ensure frame boundary flags are properly set.
diff --git a/modules/video_coding/packet_buffer.h b/modules/video_coding/packet_buffer.h index f17b00e..f8db43f 100644 --- a/modules/video_coding/packet_buffer.h +++ b/modules/video_coding/packet_buffer.h
@@ -11,6 +11,7 @@ #ifndef MODULES_VIDEO_CODING_PACKET_BUFFER_H_ #define MODULES_VIDEO_CODING_PACKET_BUFFER_H_ +#include <bit> #include <cstddef> #include <cstdint> #include <memory> @@ -22,6 +23,7 @@ #include "api/video/video_codec_type.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "modules/rtp_rtcp/source/rtp_video_header.h" +#include "rtc_base/checks.h" #include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/numerics/sequence_number_util.h" @@ -100,6 +102,16 @@ void UpdateMissingPackets(uint16_t seq_num); + static size_t Index(uint16_t seq_num, size_t buffer_size) { + RTC_DCHECK(std::has_single_bit(buffer_size)); + size_t mask = buffer_size - 1; + return seq_num & mask; + } + + size_t Index(uint16_t seq_num) const { + return Index(seq_num, buffer_.size()); + } + // buffer_.size() and max_size_ must always be a power of two. const size_t max_size_;