Allow for reordering around IRAPs.
Bug: webrtc:41480904 Change-Id: I16fb4466bff8a0c192467332413205cb9958674e Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/355482 Reviewed-by: Sergey Silkin <ssilkin@webrtc.org> Commit-Queue: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42537}
This commit is contained in:
parent
889402ee1f
commit
accef6ad5d
@ -12,6 +12,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@ -72,6 +73,16 @@ bool HasSps(const H26xPacketBuffer::Packet& packet) {
|
||||
});
|
||||
}
|
||||
|
||||
int64_t* GetContinuousSequence(rtc::ArrayView<int64_t> last_continuous,
|
||||
int64_t unwrapped_seq_num) {
|
||||
for (int64_t& last : last_continuous) {
|
||||
if (unwrapped_seq_num - 1 == last) {
|
||||
return &last;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef RTC_ENABLE_H265
|
||||
bool HasVps(const H26xPacketBuffer::Packet& packet) {
|
||||
std::vector<H265::NaluIndex> nalu_indices = H265::FindNaluIndices(
|
||||
@ -88,7 +99,9 @@ bool HasVps(const H26xPacketBuffer::Packet& packet) {
|
||||
} // namespace
|
||||
|
||||
H26xPacketBuffer::H26xPacketBuffer(bool h264_idr_only_keyframes_allowed)
|
||||
: h264_idr_only_keyframes_allowed_(h264_idr_only_keyframes_allowed) {}
|
||||
: h264_idr_only_keyframes_allowed_(h264_idr_only_keyframes_allowed) {
|
||||
last_continuous_in_sequence_.fill(std::numeric_limits<int64_t>::min());
|
||||
}
|
||||
|
||||
H26xPacketBuffer::InsertResult H26xPacketBuffer::InsertPacket(
|
||||
std::unique_ptr<Packet> packet) {
|
||||
@ -138,18 +151,25 @@ H26xPacketBuffer::InsertResult H26xPacketBuffer::FindFrames(
|
||||
|
||||
// Check if the packet is continuous or the beginning of a new coded video
|
||||
// sequence.
|
||||
if (unwrapped_seq_num - 1 != last_continuous_unwrapped_seq_num_) {
|
||||
if (unwrapped_seq_num <= last_continuous_unwrapped_seq_num_ ||
|
||||
!BeginningOfStream(*packet)) {
|
||||
int64_t* last_continuous_unwrapped_seq_num =
|
||||
GetContinuousSequence(last_continuous_in_sequence_, unwrapped_seq_num);
|
||||
if (last_continuous_unwrapped_seq_num == nullptr) {
|
||||
if (!BeginningOfStream(*packet)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
last_continuous_unwrapped_seq_num_ = unwrapped_seq_num;
|
||||
last_continuous_in_sequence_[last_continuous_in_sequence_index_] =
|
||||
unwrapped_seq_num;
|
||||
last_continuous_unwrapped_seq_num =
|
||||
&last_continuous_in_sequence_[last_continuous_in_sequence_index_];
|
||||
last_continuous_in_sequence_index_ =
|
||||
(last_continuous_in_sequence_index_ + 1) %
|
||||
last_continuous_in_sequence_.size();
|
||||
}
|
||||
|
||||
for (int64_t seq_num = unwrapped_seq_num;
|
||||
seq_num < unwrapped_seq_num + kBufferSize;) {
|
||||
RTC_DCHECK_GE(seq_num, *last_continuous_unwrapped_seq_num_);
|
||||
RTC_DCHECK_GE(seq_num, *last_continuous_unwrapped_seq_num);
|
||||
|
||||
// Packets that were never assembled into a completed frame will stay in
|
||||
// the 'buffer_'. Check that the `packet` sequence number match the expected
|
||||
@ -158,7 +178,7 @@ H26xPacketBuffer::InsertResult H26xPacketBuffer::FindFrames(
|
||||
return result;
|
||||
}
|
||||
|
||||
last_continuous_unwrapped_seq_num_ = seq_num;
|
||||
*last_continuous_unwrapped_seq_num = seq_num;
|
||||
// Last packet of the frame, try to assemble the frame.
|
||||
if (packet->marker_bit) {
|
||||
uint32_t rtp_timestamp = packet->timestamp;
|
||||
|
||||
@ -72,6 +72,7 @@ class H26xPacketBuffer {
|
||||
};
|
||||
|
||||
static constexpr int kBufferSize = 2048;
|
||||
static constexpr int kNumTrackedSequences = 5;
|
||||
|
||||
std::unique_ptr<Packet>& GetPacket(int64_t unwrapped_seq_num);
|
||||
bool BeginningOfStream(const Packet& packet) const;
|
||||
@ -91,7 +92,8 @@ class H26xPacketBuffer {
|
||||
// Indicates whether IDR frames without SPS and PPS are allowed.
|
||||
const bool h264_idr_only_keyframes_allowed_;
|
||||
std::array<std::unique_ptr<Packet>, kBufferSize> buffer_;
|
||||
absl::optional<int64_t> last_continuous_unwrapped_seq_num_;
|
||||
std::array<int64_t, kNumTrackedSequences> last_continuous_in_sequence_;
|
||||
int64_t last_continuous_in_sequence_index_ = 0;
|
||||
SeqNumUnwrapper<uint16_t> seq_num_unwrapper_;
|
||||
|
||||
// Map from pps_pic_parameter_set_id to the PPS payload associated with this
|
||||
|
||||
@ -1043,6 +1043,72 @@ TEST(H26xPacketBufferTest, FullPacketBufferDoesNotBlockKeyframe) {
|
||||
SizeIs(1));
|
||||
}
|
||||
|
||||
TEST(H26xPacketBufferTest, AssembleFrameAfterReordering) {
|
||||
H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
|
||||
|
||||
EXPECT_THAT(packet_buffer
|
||||
.InsertPacket(H264Packet(kH264StapA)
|
||||
.Sps()
|
||||
.Pps()
|
||||
.Idr()
|
||||
.SeqNum(2)
|
||||
.Time(2)
|
||||
.Marker()
|
||||
.Build())
|
||||
.packets,
|
||||
SizeIs(1));
|
||||
|
||||
EXPECT_THAT(packet_buffer
|
||||
.InsertPacket(H264Packet(kH264SingleNalu)
|
||||
.Slice()
|
||||
.SeqNum(1)
|
||||
.Time(1)
|
||||
.Marker()
|
||||
.Build())
|
||||
.packets,
|
||||
IsEmpty());
|
||||
|
||||
EXPECT_THAT(packet_buffer
|
||||
.InsertPacket(H264Packet(kH264StapA)
|
||||
.Sps()
|
||||
.Pps()
|
||||
.Idr()
|
||||
.SeqNum(0)
|
||||
.Time(0)
|
||||
.Marker()
|
||||
.Build())
|
||||
.packets,
|
||||
SizeIs(2));
|
||||
}
|
||||
|
||||
TEST(H26xPacketBufferTest, AssembleFrameAfterLoss) {
|
||||
H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false);
|
||||
|
||||
EXPECT_THAT(packet_buffer
|
||||
.InsertPacket(H264Packet(kH264StapA)
|
||||
.Sps()
|
||||
.Pps()
|
||||
.Idr()
|
||||
.SeqNum(0)
|
||||
.Time(0)
|
||||
.Marker()
|
||||
.Build())
|
||||
.packets,
|
||||
SizeIs(1));
|
||||
|
||||
EXPECT_THAT(packet_buffer
|
||||
.InsertPacket(H264Packet(kH264StapA)
|
||||
.Sps()
|
||||
.Pps()
|
||||
.Idr()
|
||||
.SeqNum(2)
|
||||
.Time(2)
|
||||
.Marker()
|
||||
.Build())
|
||||
.packets,
|
||||
SizeIs(1));
|
||||
}
|
||||
|
||||
#ifdef RTC_ENABLE_H265
|
||||
TEST(H26xPacketBufferTest, H265VpsSpsPpsIdrIsKeyframe) {
|
||||
H26xPacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user