webrtc/modules/video_coding/packet_buffer.h
Danil Chapovalov ac15a137ac In RtpVideoStreamReceiver do not rely on RTP sequence number unwrap to be stable
Currently this class assumed that if the same RTP sequence number is unwrapped again result would be the same.
That might not be true when several packets were inserted in between these two calls and unwrapper changed its state

This CL propose instead to unwrap once, and save the result in the intermediate struct.
To minimize the change and the risk, only redundant unwrapping is replaced to use unwrapped sequence number

Bug: webrtc:353565743
Change-Id: I8a18c8c206a0e16010951cabcf81dd9cb1588eda
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/357660
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42662}
2024-07-22 15:42:12 +00:00

133 lines
4.2 KiB
C++

/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_VIDEO_CODING_PACKET_BUFFER_H_
#define MODULES_VIDEO_CODING_PACKET_BUFFER_H_
#include <memory>
#include <queue>
#include <set>
#include <vector>
#include "absl/base/attributes.h"
#include "api/rtp_packet_info.h"
#include "api/units/timestamp.h"
#include "api/video/encoded_image.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "modules/rtp_rtcp/source/rtp_video_header.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/numerics/sequence_number_util.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
namespace video_coding {
class PacketBuffer {
public:
struct Packet {
Packet() = default;
Packet(const RtpPacketReceived& rtp_packet,
int64_t sequence_number,
const RTPVideoHeader& video_header);
Packet(const Packet&) = delete;
Packet(Packet&&) = delete;
Packet& operator=(const Packet&) = delete;
Packet& operator=(Packet&&) = delete;
~Packet() = default;
VideoCodecType codec() const { return video_header.codec; }
int width() const { return video_header.width; }
int height() const { return video_header.height; }
bool is_first_packet_in_frame() const {
return video_header.is_first_packet_in_frame;
}
bool is_last_packet_in_frame() const {
return video_header.is_last_packet_in_frame;
}
uint16_t seq_num() const { return static_cast<uint16_t>(sequence_number); }
// If all its previous packets have been inserted into the packet buffer.
// Set and used internally by the PacketBuffer.
bool continuous = false;
bool marker_bit = false;
uint8_t payload_type = 0;
int64_t sequence_number = 0;
uint32_t timestamp = 0;
int times_nacked = -1;
rtc::CopyOnWriteBuffer video_payload;
RTPVideoHeader video_header;
};
struct InsertResult {
std::vector<std::unique_ptr<Packet>> packets;
// Indicates if the packet buffer was cleared, which means that a key
// frame request should be sent.
bool buffer_cleared = false;
};
// Both `start_buffer_size` and `max_buffer_size` must be a power of 2.
PacketBuffer(size_t start_buffer_size, size_t max_buffer_size);
~PacketBuffer();
ABSL_MUST_USE_RESULT InsertResult
InsertPacket(std::unique_ptr<Packet> packet);
ABSL_MUST_USE_RESULT InsertResult InsertPadding(uint16_t seq_num);
void ClearTo(uint16_t seq_num);
void Clear();
void ForceSpsPpsIdrIsH264Keyframe();
void ResetSpsPpsIdrIsH264Keyframe();
private:
void ClearInternal();
// Tries to expand the buffer.
bool ExpandBufferSize();
// Test if all previous packets has arrived for the given sequence number.
bool PotentialNewFrame(uint16_t seq_num) const;
// Test if all packets of a frame has arrived, and if so, returns packets to
// create frames.
std::vector<std::unique_ptr<Packet>> FindFrames(uint16_t seq_num);
void UpdateMissingPackets(uint16_t seq_num);
// buffer_.size() and max_size_ must always be a power of two.
const size_t max_size_;
// The fist sequence number currently in the buffer.
uint16_t first_seq_num_;
// If the packet buffer has received its first packet.
bool first_packet_received_;
// If the buffer is cleared to `first_seq_num_`.
bool is_cleared_to_first_seq_num_;
// Buffer that holds the the inserted packets and information needed to
// determine continuity between them.
std::vector<std::unique_ptr<Packet>> buffer_;
absl::optional<uint16_t> newest_inserted_seq_num_;
std::set<uint16_t, DescendingSeqNumComp<uint16_t>> missing_packets_;
std::set<uint16_t, DescendingSeqNumComp<uint16_t>> received_padding_;
// Indicates if we should require SPS, PPS, and IDR for a particular
// RTP timestamp to treat the corresponding frame as a keyframe.
bool sps_pps_idr_is_h264_keyframe_;
};
} // namespace video_coding
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_PACKET_BUFFER_H_