Index: webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc |
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc |
index 1f926d9eeb010246d7fa06190798f60eddd8b2d4..c45c212d1c4fcf305d937d77579e9125861d4b63 100644 |
--- a/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc |
+++ b/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc |
@@ -63,10 +63,12 @@ void CreateThreeFragments(RTPFragmentationHeader* fragmentation, |
} |
RtpPacketizer* CreateH264Packetizer(H264PacketizationMode mode, |
- size_t max_payload_size) { |
+ size_t max_payload_size, |
+ size_t last_packet_reduction) { |
RTPVideoTypeHeader type_header; |
type_header.H264.packetization_mode = mode; |
- return RtpPacketizer::Create(kRtpVideoH264, max_payload_size, &type_header, |
+ return RtpPacketizer::Create(kRtpVideoH264, max_payload_size, |
+ last_packet_reduction, &type_header, |
kEmptyFrame); |
} |
@@ -98,6 +100,7 @@ void VerifyFua(size_t fua_index, |
void TestFua(size_t frame_size, |
size_t max_payload_size, |
+ size_t last_packet_reduction, |
const std::vector<size_t>& expected_sizes) { |
std::unique_ptr<uint8_t[]> frame; |
frame.reset(new uint8_t[frame_size]); |
@@ -109,22 +112,23 @@ void TestFua(size_t frame_size, |
fragmentation.VerifyAndAllocateFragmentationHeader(1); |
fragmentation.fragmentationOffset[0] = 0; |
fragmentation.fragmentationLength[0] = frame_size; |
- std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( |
- H264PacketizationMode::NonInterleaved, max_payload_size)); |
- packetizer->SetPayloadData(frame.get(), frame_size, &fragmentation); |
+ std::unique_ptr<RtpPacketizer> packetizer( |
+ CreateH264Packetizer(H264PacketizationMode::NonInterleaved, |
+ max_payload_size, last_packet_reduction)); |
+ EXPECT_EQ( |
+ expected_sizes.size(), |
+ packetizer->SetPayloadData(frame.get(), frame_size, &fragmentation)); |
RtpPacketToSend packet(kNoExtensions); |
ASSERT_LE(max_payload_size, packet.FreeCapacity()); |
- bool last = false; |
size_t offset = kNalHeaderSize; |
for (size_t i = 0; i < expected_sizes.size(); ++i) { |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
VerifyFua(i, frame.get(), offset, packet.payload(), expected_sizes); |
- EXPECT_EQ(i == expected_sizes.size() - 1, last) << "FUA index: " << i; |
offset += expected_sizes[i]; |
} |
- EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
+ EXPECT_FALSE(packetizer->NextPacket(&packet)); |
} |
size_t GetExpectedNaluOffset(const RTPFragmentationHeader& fragmentation, |
@@ -182,16 +186,15 @@ TEST_P(RtpPacketizerH264ModeTest, TestSingleNalu) { |
fragmentation.fragmentationOffset[0] = 0; |
fragmentation.fragmentationLength[0] = sizeof(frame); |
std::unique_ptr<RtpPacketizer> packetizer( |
- CreateH264Packetizer(GetParam(), kMaxPayloadSize)); |
- packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation); |
+ CreateH264Packetizer(GetParam(), kMaxPayloadSize, 0)); |
+ ASSERT_EQ(1u, |
+ packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation)); |
RtpPacketToSend packet(kNoExtensions); |
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
- bool last = false; |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
EXPECT_EQ(2u, packet.payload_size()); |
- EXPECT_TRUE(last); |
VerifySingleNaluPayload(fragmentation, 0, frame, packet.payload()); |
- EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
+ EXPECT_FALSE(packetizer->NextPacket(&packet)); |
} |
TEST_P(RtpPacketizerH264ModeTest, TestSingleNaluTwoPackets) { |
@@ -210,21 +213,19 @@ TEST_P(RtpPacketizerH264ModeTest, TestSingleNaluTwoPackets) { |
frame[fragmentation.fragmentationOffset[1]] = 0x01; |
std::unique_ptr<RtpPacketizer> packetizer( |
- CreateH264Packetizer(GetParam(), kMaxPayloadSize)); |
- packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
+ CreateH264Packetizer(GetParam(), kMaxPayloadSize, 0)); |
+ ASSERT_EQ(2u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation)); |
RtpPacketToSend packet(kNoExtensions); |
- bool last = false; |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
ASSERT_EQ(fragmentation.fragmentationOffset[1], packet.payload_size()); |
VerifySingleNaluPayload(fragmentation, 0, frame, packet.payload()); |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
ASSERT_EQ(fragmentation.fragmentationLength[1], packet.payload_size()); |
VerifySingleNaluPayload(fragmentation, 1, frame, packet.payload()); |
- EXPECT_TRUE(last); |
- EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
+ EXPECT_FALSE(packetizer->NextPacket(&packet)); |
} |
INSTANTIATE_TEST_CASE_P( |
@@ -245,21 +246,63 @@ TEST(RtpPacketizerH264Test, TestStapA) { |
RTPFragmentationHeader fragmentation; |
CreateThreeFragments(&fragmentation, kFrameSize, kPayloadOffset); |
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( |
- H264PacketizationMode::NonInterleaved, kMaxPayloadSize)); |
- packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
+ H264PacketizationMode::NonInterleaved, kMaxPayloadSize, 0)); |
+ ASSERT_EQ(1u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation)); |
RtpPacketToSend packet(kNoExtensions); |
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
- bool last = false; |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
size_t expected_packet_size = |
kNalHeaderSize + 3 * kLengthFieldLength + kFrameSize; |
ASSERT_EQ(expected_packet_size, packet.payload_size()); |
- EXPECT_TRUE(last); |
+ |
for (size_t i = 0; i < fragmentation.fragmentationVectorSize; ++i) |
VerifyStapAPayload(fragmentation, 0, i, frame, packet.payload()); |
- EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
+ EXPECT_FALSE(packetizer->NextPacket(&packet)); |
+} |
+ |
+TEST(RtpPacketizerH264Test, TestStapARespectsPacketReduction) { |
+ const size_t kLastPacketReduction = 100; |
+ const size_t kFrameSize = kMaxPayloadSize - 1 - kLastPacketReduction; |
+ uint8_t frame[kFrameSize] = {0x07, 0xFF, // F=0, NRI=0, Type=7. |
+ 0x08, 0xFF, // F=0, NRI=0, Type=8. |
+ 0x05}; // F=0, NRI=0, Type=5. |
+ const size_t kPayloadOffset = 5; |
+ for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i) |
+ frame[i + kPayloadOffset] = i; |
+ RTPFragmentationHeader fragmentation; |
+ fragmentation.VerifyAndAllocateFragmentationHeader(3); |
+ fragmentation.fragmentationOffset[0] = 0; |
+ fragmentation.fragmentationLength[0] = 2; |
+ fragmentation.fragmentationOffset[1] = 2; |
+ fragmentation.fragmentationLength[1] = 2; |
+ fragmentation.fragmentationOffset[2] = 4; |
+ fragmentation.fragmentationLength[2] = |
+ kNalHeaderSize + kFrameSize - kPayloadOffset; |
+ std::unique_ptr<RtpPacketizer> packetizer( |
+ CreateH264Packetizer(H264PacketizationMode::NonInterleaved, |
+ kMaxPayloadSize, kLastPacketReduction)); |
+ ASSERT_EQ(2u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation)); |
+ |
+ RtpPacketToSend packet(kNoExtensions); |
+ ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
+ size_t expected_packet_size = kNalHeaderSize; |
+ for (size_t i = 0; i < 2; ++i) { |
+ expected_packet_size += |
+ kLengthFieldLength + fragmentation.fragmentationLength[i]; |
+ } |
+ ASSERT_EQ(expected_packet_size, packet.payload_size()); |
+ for (size_t i = 0; i < 2; ++i) |
+ VerifyStapAPayload(fragmentation, 0, i, frame, packet.payload()); |
+ |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
+ expected_packet_size = fragmentation.fragmentationLength[2]; |
+ ASSERT_EQ(expected_packet_size, packet.payload_size()); |
+ VerifySingleNaluPayload(fragmentation, 2, frame, packet.payload()); |
+ |
+ EXPECT_FALSE(packetizer->NextPacket(&packet)); |
} |
TEST(RtpPacketizerH264Test, TestSingleNalUnitModeHasNoStapA) { |
@@ -275,16 +318,15 @@ TEST(RtpPacketizerH264Test, TestSingleNalUnitModeHasNoStapA) { |
RTPFragmentationHeader fragmentation; |
CreateThreeFragments(&fragmentation, kFrameSize, kPayloadOffset); |
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( |
- H264PacketizationMode::SingleNalUnit, kMaxPayloadSize)); |
+ H264PacketizationMode::SingleNalUnit, kMaxPayloadSize, 0)); |
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
RtpPacketToSend packet(kNoExtensions); |
- bool last = false; |
// The three fragments should be returned as three packets. |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
- EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
+ EXPECT_FALSE(packetizer->NextPacket(&packet)); |
} |
TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) { |
@@ -305,30 +347,27 @@ TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) { |
fragmentation.fragmentationLength[2] = |
kNalHeaderSize + kFrameSize - kPayloadOffset; |
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( |
- H264PacketizationMode::NonInterleaved, kMaxPayloadSize)); |
- packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
+ H264PacketizationMode::NonInterleaved, kMaxPayloadSize, 0)); |
+ ASSERT_EQ(2u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation)); |
RtpPacketToSend packet(kNoExtensions); |
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
- bool last = false; |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
size_t expected_packet_size = kNalHeaderSize; |
for (size_t i = 0; i < 2; ++i) { |
expected_packet_size += |
kLengthFieldLength + fragmentation.fragmentationLength[i]; |
} |
ASSERT_EQ(expected_packet_size, packet.payload_size()); |
- EXPECT_FALSE(last); |
for (size_t i = 0; i < 2; ++i) |
VerifyStapAPayload(fragmentation, 0, i, frame, packet.payload()); |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
expected_packet_size = fragmentation.fragmentationLength[2]; |
ASSERT_EQ(expected_packet_size, packet.payload_size()); |
- EXPECT_TRUE(last); |
VerifySingleNaluPayload(fragmentation, 2, frame, packet.payload()); |
- EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
+ EXPECT_FALSE(packetizer->NextPacket(&packet)); |
} |
TEST(RtpPacketizerH264Test, TestMixedStapA_FUA) { |
@@ -353,61 +392,64 @@ TEST(RtpPacketizerH264Test, TestMixedStapA_FUA) { |
} |
} |
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( |
- H264PacketizationMode::NonInterleaved, kMaxPayloadSize)); |
- packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
+ H264PacketizationMode::NonInterleaved, kMaxPayloadSize, 0)); |
+ ASSERT_EQ(3u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation)); |
// First expecting two FU-A packets. |
std::vector<size_t> fua_sizes; |
- fua_sizes.push_back(1100); |
fua_sizes.push_back(1099); |
+ fua_sizes.push_back(1100); |
RtpPacketToSend packet(kNoExtensions); |
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
- bool last = false; |
int fua_offset = kNalHeaderSize; |
for (size_t i = 0; i < 2; ++i) { |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
VerifyFua(i, frame, fua_offset, packet.payload(), fua_sizes); |
- EXPECT_FALSE(last); |
fua_offset += fua_sizes[i]; |
} |
// Then expecting one STAP-A packet with two nal units. |
- ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
+ ASSERT_TRUE(packetizer->NextPacket(&packet)); |
size_t expected_packet_size = |
kNalHeaderSize + 2 * kLengthFieldLength + 2 * kStapANaluSize; |
ASSERT_EQ(expected_packet_size, packet.payload_size()); |
- EXPECT_TRUE(last); |
for (size_t i = 1; i < fragmentation.fragmentationVectorSize; ++i) |
VerifyStapAPayload(fragmentation, 1, i, frame, packet.payload()); |
- EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
+ EXPECT_FALSE(packetizer->NextPacket(&packet)); |
} |
TEST(RtpPacketizerH264Test, TestFUAOddSize) { |
const size_t kExpectedPayloadSizes[2] = {600, 600}; |
TestFua( |
- kMaxPayloadSize + 1, |
- kMaxPayloadSize, |
+ kMaxPayloadSize + 1, kMaxPayloadSize, 0, |
+ std::vector<size_t>(kExpectedPayloadSizes, |
+ kExpectedPayloadSizes + |
+ sizeof(kExpectedPayloadSizes) / sizeof(size_t))); |
+} |
+ |
+TEST(RtpPacketizerH264Test, TestFUAWithLastPacketReduction) { |
+ const size_t kExpectedPayloadSizes[2] = {601, 597}; |
+ TestFua( |
+ kMaxPayloadSize - 1, kMaxPayloadSize, 4, |
std::vector<size_t>(kExpectedPayloadSizes, |
kExpectedPayloadSizes + |
sizeof(kExpectedPayloadSizes) / sizeof(size_t))); |
} |
TEST(RtpPacketizerH264Test, TestFUAEvenSize) { |
- const size_t kExpectedPayloadSizes[2] = {601, 600}; |
+ const size_t kExpectedPayloadSizes[2] = {600, 601}; |
TestFua( |
- kMaxPayloadSize + 2, |
- kMaxPayloadSize, |
+ kMaxPayloadSize + 2, kMaxPayloadSize, 0, |
std::vector<size_t>(kExpectedPayloadSizes, |
kExpectedPayloadSizes + |
sizeof(kExpectedPayloadSizes) / sizeof(size_t))); |
} |
TEST(RtpPacketizerH264Test, TestFUARounding) { |
- const size_t kExpectedPayloadSizes[8] = {1266, 1266, 1266, 1266, |
- 1266, 1266, 1266, 1261}; |
+ const size_t kExpectedPayloadSizes[8] = {1265, 1265, 1265, 1265, |
+ 1265, 1266, 1266, 1266}; |
TestFua( |
- 10124, |
- 1448, |
+ 10124, 1448, 0, |
std::vector<size_t>(kExpectedPayloadSizes, |
kExpectedPayloadSizes + |
sizeof(kExpectedPayloadSizes) / sizeof(size_t))); |
@@ -419,8 +461,8 @@ TEST(RtpPacketizerH264Test, TestFUABig) { |
// Generate 10 full sized packets, leave room for FU-A headers minus the NALU |
// header. |
TestFua( |
- 10 * (kMaxPayloadSize - kFuAHeaderSize) + kNalHeaderSize, |
- kMaxPayloadSize, |
+ 10 * (kMaxPayloadSize - kFuAHeaderSize) + kNalHeaderSize, kMaxPayloadSize, |
+ 0, |
std::vector<size_t>(kExpectedPayloadSizes, |
kExpectedPayloadSizes + |
sizeof(kExpectedPayloadSizes) / sizeof(size_t))); |
@@ -441,7 +483,7 @@ TEST(RtpPacketizerH264DeathTest, SendOverlongDataInPacketizationMode0) { |
frame[fragmentation.fragmentationOffset[0]] = 0x01; |
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( |
- H264PacketizationMode::SingleNalUnit, kMaxPayloadSize)); |
+ H264PacketizationMode::SingleNalUnit, kMaxPayloadSize, 0)); |
EXPECT_DEATH(packetizer->SetPayloadData(frame, kFrameSize, &fragmentation), |
"payload_size"); |
} |
@@ -490,23 +532,22 @@ TEST_F(RtpPacketizerH264TestSpsRewriting, FuASps) { |
// Set size to fragment SPS into two FU-A packets. |
packetizer_.reset( |
CreateH264Packetizer(H264PacketizationMode::NonInterleaved, |
- sizeof(kOriginalSps) - 2 + kHeaderOverhead)); |
+ sizeof(kOriginalSps) - 2 + kHeaderOverhead, 0)); |
packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(), |
&fragmentation_header_); |
- bool last_packet = true; |
RtpPacketToSend packet(kNoExtensions); |
ASSERT_LE(sizeof(kOriginalSps) + kHeaderOverhead, packet.FreeCapacity()); |
- EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet)); |
+ EXPECT_TRUE(packetizer_->NextPacket(&packet)); |
size_t offset = H264::kNaluTypeSize; |
size_t length = packet.payload_size() - kFuAHeaderSize; |
EXPECT_THAT(packet.payload().subview(kFuAHeaderSize), |
ElementsAreArray(&kRewrittenSps[offset], length)); |
offset += length; |
- EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet)); |
+ EXPECT_TRUE(packetizer_->NextPacket(&packet)); |
length = packet.payload_size() - kFuAHeaderSize; |
EXPECT_THAT(packet.payload().subview(kFuAHeaderSize), |
ElementsAreArray(&kRewrittenSps[offset], length)); |
@@ -523,16 +564,16 @@ TEST_F(RtpPacketizerH264TestSpsRewriting, StapASps) { |
// Set size to include SPS and the rest of the packets in a Stap-A package. |
packetizer_.reset(CreateH264Packetizer(H264PacketizationMode::NonInterleaved, |
- kExpectedTotalSize + kHeaderOverhead)); |
+ kExpectedTotalSize + kHeaderOverhead, |
+ 0)); |
packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(), |
&fragmentation_header_); |
- bool last_packet = true; |
RtpPacketToSend packet(kNoExtensions); |
ASSERT_LE(kExpectedTotalSize + kHeaderOverhead, packet.FreeCapacity()); |
- EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet)); |
+ EXPECT_TRUE(packetizer_->NextPacket(&packet)); |
EXPECT_EQ(kExpectedTotalSize, packet.payload_size()); |
EXPECT_THAT(packet.payload().subview(H264::kNaluTypeSize + kLengthFieldLength, |
sizeof(kRewrittenSps)), |