OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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 |
11 #include <memory> | 11 #include <memory> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
| 14 #include "webrtc/base/array_view.h" |
14 #include "webrtc/common_video/h264/h264_common.h" | 15 #include "webrtc/common_video/h264/h264_common.h" |
15 #include "webrtc/modules/include/module_common_types.h" | 16 #include "webrtc/modules/include/module_common_types.h" |
16 #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" | 17 #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" |
17 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 18 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
18 #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" | 19 #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" |
| 20 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
19 #include "webrtc/test/gmock.h" | 21 #include "webrtc/test/gmock.h" |
20 #include "webrtc/test/gtest.h" | 22 #include "webrtc/test/gtest.h" |
21 | 23 |
22 namespace webrtc { | 24 namespace webrtc { |
23 namespace { | 25 namespace { |
| 26 |
| 27 using ::testing::ElementsAreArray; |
| 28 |
| 29 constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr; |
24 const size_t kMaxPayloadSize = 1200; | 30 const size_t kMaxPayloadSize = 1200; |
25 const size_t kLengthFieldLength = 2; | 31 const size_t kLengthFieldLength = 2; |
26 | 32 |
27 enum Nalu { | 33 enum Nalu { |
28 kSlice = 1, | 34 kSlice = 1, |
29 kIdr = 5, | 35 kIdr = 5, |
30 kSei = 6, | 36 kSei = 6, |
31 kSps = 7, | 37 kSps = 7, |
32 kPps = 8, | 38 kPps = 8, |
33 kStapA = 24, | 39 kStapA = 24, |
34 kFuA = 28 | 40 kFuA = 28 |
35 }; | 41 }; |
36 | 42 |
37 static const size_t kNalHeaderSize = 1; | 43 static const size_t kNalHeaderSize = 1; |
38 static const size_t kFuAHeaderSize = 2; | 44 static const size_t kFuAHeaderSize = 2; |
39 | 45 |
40 // Bit masks for FU (A and B) indicators. | 46 // Bit masks for FU (A and B) indicators. |
41 enum NalDefs { kFBit = 0x80, kNriMask = 0x60, kTypeMask = 0x1F }; | 47 enum NalDefs { kFBit = 0x80, kNriMask = 0x60, kTypeMask = 0x1F }; |
42 | 48 |
43 // Bit masks for FU (A and B) headers. | 49 // Bit masks for FU (A and B) headers. |
44 enum FuDefs { kSBit = 0x80, kEBit = 0x40, kRBit = 0x20 }; | 50 enum FuDefs { kSBit = 0x80, kEBit = 0x40, kRBit = 0x20 }; |
45 | 51 |
46 void VerifyFua(size_t fua_index, | 52 void VerifyFua(size_t fua_index, |
47 const uint8_t* expected_payload, | 53 const uint8_t* expected_payload, |
48 int offset, | 54 int offset, |
49 const uint8_t* packet, | 55 rtc::ArrayView<const uint8_t> packet, |
50 size_t length, | |
51 const std::vector<size_t>& expected_sizes) { | 56 const std::vector<size_t>& expected_sizes) { |
52 ASSERT_EQ(expected_sizes[fua_index] + kFuAHeaderSize, length) | 57 ASSERT_EQ(expected_sizes[fua_index] + kFuAHeaderSize, packet.size()) |
53 << "FUA index: " << fua_index; | 58 << "FUA index: " << fua_index; |
54 const uint8_t kFuIndicator = 0x1C; // F=0, NRI=0, Type=28. | 59 const uint8_t kFuIndicator = 0x1C; // F=0, NRI=0, Type=28. |
55 EXPECT_EQ(kFuIndicator, packet[0]) << "FUA index: " << fua_index; | 60 EXPECT_EQ(kFuIndicator, packet[0]) << "FUA index: " << fua_index; |
56 bool should_be_last_fua = (fua_index == expected_sizes.size() - 1); | 61 bool should_be_last_fua = (fua_index == expected_sizes.size() - 1); |
57 uint8_t fu_header = 0; | 62 uint8_t fu_header = 0; |
58 if (fua_index == 0) | 63 if (fua_index == 0) |
59 fu_header = 0x85; // S=1, E=0, R=0, Type=5. | 64 fu_header = 0x85; // S=1, E=0, R=0, Type=5. |
60 else if (should_be_last_fua) | 65 else if (should_be_last_fua) |
61 fu_header = 0x45; // S=0, E=1, R=0, Type=5. | 66 fu_header = 0x45; // S=0, E=1, R=0, Type=5. |
62 else | 67 else |
63 fu_header = 0x05; // S=0, E=0, R=0, Type=5. | 68 fu_header = 0x05; // S=0, E=0, R=0, Type=5. |
64 EXPECT_EQ(fu_header, packet[1]) << "FUA index: " << fua_index; | 69 EXPECT_EQ(fu_header, packet[1]) << "FUA index: " << fua_index; |
65 std::vector<uint8_t> expected_packet_payload( | 70 std::vector<uint8_t> expected_packet_payload( |
66 &expected_payload[offset], | 71 &expected_payload[offset], |
67 &expected_payload[offset + expected_sizes[fua_index]]); | 72 &expected_payload[offset + expected_sizes[fua_index]]); |
68 EXPECT_THAT( | 73 EXPECT_THAT(expected_packet_payload, |
69 expected_packet_payload, | 74 ElementsAreArray(&packet[2], expected_sizes[fua_index])) |
70 ::testing::ElementsAreArray(&packet[2], expected_sizes[fua_index])) | |
71 << "FUA index: " << fua_index; | 75 << "FUA index: " << fua_index; |
72 } | 76 } |
73 | 77 |
74 void TestFua(size_t frame_size, | 78 void TestFua(size_t frame_size, |
75 size_t max_payload_size, | 79 size_t max_payload_size, |
76 const std::vector<size_t>& expected_sizes) { | 80 const std::vector<size_t>& expected_sizes) { |
77 std::unique_ptr<uint8_t[]> frame; | 81 std::unique_ptr<uint8_t[]> frame; |
78 frame.reset(new uint8_t[frame_size]); | 82 frame.reset(new uint8_t[frame_size]); |
79 frame[0] = 0x05; // F=0, NRI=0, Type=5. | 83 frame[0] = 0x05; // F=0, NRI=0, Type=5. |
80 for (size_t i = 0; i < frame_size - kNalHeaderSize; ++i) { | 84 for (size_t i = 0; i < frame_size - kNalHeaderSize; ++i) { |
81 frame[i + kNalHeaderSize] = i; | 85 frame[i + kNalHeaderSize] = i; |
82 } | 86 } |
83 RTPFragmentationHeader fragmentation; | 87 RTPFragmentationHeader fragmentation; |
84 fragmentation.VerifyAndAllocateFragmentationHeader(1); | 88 fragmentation.VerifyAndAllocateFragmentationHeader(1); |
85 fragmentation.fragmentationOffset[0] = 0; | 89 fragmentation.fragmentationOffset[0] = 0; |
86 fragmentation.fragmentationLength[0] = frame_size; | 90 fragmentation.fragmentationLength[0] = frame_size; |
87 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 91 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |
88 kRtpVideoH264, max_payload_size, NULL, kEmptyFrame)); | 92 kRtpVideoH264, max_payload_size, NULL, kEmptyFrame)); |
89 packetizer->SetPayloadData(frame.get(), frame_size, &fragmentation); | 93 packetizer->SetPayloadData(frame.get(), frame_size, &fragmentation); |
90 | 94 |
91 std::unique_ptr<uint8_t[]> packet(new uint8_t[max_payload_size]); | 95 RtpPacketToSend packet(kNoExtensions); |
92 size_t length = 0; | 96 ASSERT_LE(max_payload_size, packet.FreeCapacity()); |
93 bool last = false; | 97 bool last = false; |
94 size_t offset = kNalHeaderSize; | 98 size_t offset = kNalHeaderSize; |
95 for (size_t i = 0; i < expected_sizes.size(); ++i) { | 99 for (size_t i = 0; i < expected_sizes.size(); ++i) { |
96 ASSERT_TRUE(packetizer->NextPacket(packet.get(), &length, &last)); | 100 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
97 VerifyFua(i, frame.get(), offset, packet.get(), length, expected_sizes); | 101 VerifyFua(i, frame.get(), offset, packet.payload(), expected_sizes); |
98 EXPECT_EQ(i == expected_sizes.size() - 1, last) << "FUA index: " << i; | 102 EXPECT_EQ(i == expected_sizes.size() - 1, last) << "FUA index: " << i; |
99 offset += expected_sizes[i]; | 103 offset += expected_sizes[i]; |
100 } | 104 } |
101 | 105 |
102 EXPECT_FALSE(packetizer->NextPacket(packet.get(), &length, &last)); | 106 EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
103 } | 107 } |
104 | 108 |
105 size_t GetExpectedNaluOffset(const RTPFragmentationHeader& fragmentation, | 109 size_t GetExpectedNaluOffset(const RTPFragmentationHeader& fragmentation, |
106 size_t start_index, | 110 size_t start_index, |
107 size_t nalu_index) { | 111 size_t nalu_index) { |
108 assert(nalu_index < fragmentation.fragmentationVectorSize); | 112 assert(nalu_index < fragmentation.fragmentationVectorSize); |
109 size_t expected_nalu_offset = kNalHeaderSize; // STAP-A header. | 113 size_t expected_nalu_offset = kNalHeaderSize; // STAP-A header. |
110 for (size_t i = start_index; i < nalu_index; ++i) { | 114 for (size_t i = start_index; i < nalu_index; ++i) { |
111 expected_nalu_offset += | 115 expected_nalu_offset += |
112 kLengthFieldLength + fragmentation.fragmentationLength[i]; | 116 kLengthFieldLength + fragmentation.fragmentationLength[i]; |
113 } | 117 } |
114 return expected_nalu_offset; | 118 return expected_nalu_offset; |
115 } | 119 } |
116 | 120 |
117 void VerifyStapAPayload(const RTPFragmentationHeader& fragmentation, | 121 void VerifyStapAPayload(const RTPFragmentationHeader& fragmentation, |
118 size_t first_stapa_index, | 122 size_t first_stapa_index, |
119 size_t nalu_index, | 123 size_t nalu_index, |
120 const uint8_t* frame, | 124 rtc::ArrayView<const uint8_t> frame, |
121 size_t frame_length, | 125 rtc::ArrayView<const uint8_t> packet) { |
122 const uint8_t* packet, | |
123 size_t packet_length) { | |
124 size_t expected_payload_offset = | 126 size_t expected_payload_offset = |
125 GetExpectedNaluOffset(fragmentation, first_stapa_index, nalu_index) + | 127 GetExpectedNaluOffset(fragmentation, first_stapa_index, nalu_index) + |
126 kLengthFieldLength; | 128 kLengthFieldLength; |
127 size_t offset = fragmentation.fragmentationOffset[nalu_index]; | 129 size_t offset = fragmentation.fragmentationOffset[nalu_index]; |
128 const uint8_t* expected_payload = &frame[offset]; | 130 const uint8_t* expected_payload = &frame[offset]; |
129 size_t expected_payload_length = | 131 size_t expected_payload_length = |
130 fragmentation.fragmentationLength[nalu_index]; | 132 fragmentation.fragmentationLength[nalu_index]; |
131 ASSERT_LE(offset + expected_payload_length, frame_length); | 133 ASSERT_LE(offset + expected_payload_length, frame.size()); |
132 ASSERT_LE(expected_payload_offset + expected_payload_length, packet_length); | 134 ASSERT_LE(expected_payload_offset + expected_payload_length, packet.size()); |
133 std::vector<uint8_t> expected_payload_vector( | 135 std::vector<uint8_t> expected_payload_vector( |
134 expected_payload, &expected_payload[expected_payload_length]); | 136 expected_payload, &expected_payload[expected_payload_length]); |
135 EXPECT_THAT(expected_payload_vector, | 137 EXPECT_THAT(expected_payload_vector, |
136 ::testing::ElementsAreArray(&packet[expected_payload_offset], | 138 ElementsAreArray(&packet[expected_payload_offset], |
137 expected_payload_length)); | 139 expected_payload_length)); |
138 } | 140 } |
139 | 141 |
140 void VerifySingleNaluPayload(const RTPFragmentationHeader& fragmentation, | 142 void VerifySingleNaluPayload(const RTPFragmentationHeader& fragmentation, |
141 size_t nalu_index, | 143 size_t nalu_index, |
142 const uint8_t* frame, | 144 rtc::ArrayView<const uint8_t> frame, |
143 size_t frame_length, | 145 rtc::ArrayView<const uint8_t> packet) { |
144 const uint8_t* packet, | 146 auto fragment = frame.subview(fragmentation.fragmentationOffset[nalu_index], |
145 size_t packet_length) { | 147 fragmentation.fragmentationLength[nalu_index]); |
146 std::vector<uint8_t> expected_payload_vector( | 148 EXPECT_THAT(packet, ElementsAreArray(fragment.begin(), fragment.end())); |
147 &frame[fragmentation.fragmentationOffset[nalu_index]], | |
148 &frame[fragmentation.fragmentationOffset[nalu_index] + | |
149 fragmentation.fragmentationLength[nalu_index]]); | |
150 EXPECT_THAT(expected_payload_vector, | |
151 ::testing::ElementsAreArray(packet, packet_length)); | |
152 } | 149 } |
153 } // namespace | 150 } // namespace |
154 | 151 |
155 TEST(RtpPacketizerH264Test, TestSingleNalu) { | 152 TEST(RtpPacketizerH264Test, TestSingleNalu) { |
156 const uint8_t frame[2] = {0x05, 0xFF}; // F=0, NRI=0, Type=5. | 153 const uint8_t frame[2] = {0x05, 0xFF}; // F=0, NRI=0, Type=5. |
157 RTPFragmentationHeader fragmentation; | 154 RTPFragmentationHeader fragmentation; |
158 fragmentation.VerifyAndAllocateFragmentationHeader(1); | 155 fragmentation.VerifyAndAllocateFragmentationHeader(1); |
159 fragmentation.fragmentationOffset[0] = 0; | 156 fragmentation.fragmentationOffset[0] = 0; |
160 fragmentation.fragmentationLength[0] = sizeof(frame); | 157 fragmentation.fragmentationLength[0] = sizeof(frame); |
161 std::unique_ptr<RtpPacketizer> packetizer( | 158 std::unique_ptr<RtpPacketizer> packetizer( |
162 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); | 159 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); |
163 packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation); | 160 packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation); |
164 uint8_t packet[kMaxPayloadSize] = {0}; | 161 RtpPacketToSend packet(kNoExtensions); |
165 size_t length = 0; | 162 ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
166 bool last = false; | 163 bool last = false; |
167 ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last)); | 164 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
168 EXPECT_EQ(2u, length); | 165 EXPECT_EQ(2u, packet.payload_size()); |
169 EXPECT_TRUE(last); | 166 EXPECT_TRUE(last); |
170 VerifySingleNaluPayload( | 167 VerifySingleNaluPayload(fragmentation, 0, frame, packet.payload()); |
171 fragmentation, 0, frame, sizeof(frame), packet, length); | 168 EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
172 EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last)); | |
173 } | 169 } |
174 | 170 |
175 TEST(RtpPacketizerH264Test, TestSingleNaluTwoPackets) { | 171 TEST(RtpPacketizerH264Test, TestSingleNaluTwoPackets) { |
176 const size_t kFrameSize = kMaxPayloadSize + 100; | 172 const size_t kFrameSize = kMaxPayloadSize + 100; |
177 uint8_t frame[kFrameSize] = {0}; | 173 uint8_t frame[kFrameSize] = {0}; |
178 for (size_t i = 0; i < kFrameSize; ++i) | 174 for (size_t i = 0; i < kFrameSize; ++i) |
179 frame[i] = i; | 175 frame[i] = i; |
180 RTPFragmentationHeader fragmentation; | 176 RTPFragmentationHeader fragmentation; |
181 fragmentation.VerifyAndAllocateFragmentationHeader(2); | 177 fragmentation.VerifyAndAllocateFragmentationHeader(2); |
182 fragmentation.fragmentationOffset[0] = 0; | 178 fragmentation.fragmentationOffset[0] = 0; |
183 fragmentation.fragmentationLength[0] = kMaxPayloadSize; | 179 fragmentation.fragmentationLength[0] = kMaxPayloadSize; |
184 fragmentation.fragmentationOffset[1] = kMaxPayloadSize; | 180 fragmentation.fragmentationOffset[1] = kMaxPayloadSize; |
185 fragmentation.fragmentationLength[1] = 100; | 181 fragmentation.fragmentationLength[1] = 100; |
186 // Set NAL headers. | 182 // Set NAL headers. |
187 frame[fragmentation.fragmentationOffset[0]] = 0x01; | 183 frame[fragmentation.fragmentationOffset[0]] = 0x01; |
188 frame[fragmentation.fragmentationOffset[1]] = 0x01; | 184 frame[fragmentation.fragmentationOffset[1]] = 0x01; |
189 | 185 |
190 std::unique_ptr<RtpPacketizer> packetizer( | 186 std::unique_ptr<RtpPacketizer> packetizer( |
191 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); | 187 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); |
192 packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); | 188 packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
193 | 189 |
194 uint8_t packet[kMaxPayloadSize] = {0}; | 190 RtpPacketToSend packet(kNoExtensions); |
195 size_t length = 0; | |
196 bool last = false; | 191 bool last = false; |
197 ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last)); | 192 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
198 ASSERT_EQ(fragmentation.fragmentationOffset[1], length); | 193 ASSERT_EQ(fragmentation.fragmentationOffset[1], packet.payload_size()); |
199 VerifySingleNaluPayload(fragmentation, 0, frame, kFrameSize, packet, length); | 194 VerifySingleNaluPayload(fragmentation, 0, frame, packet.payload()); |
200 | 195 |
201 ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last)); | 196 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
202 ASSERT_EQ(fragmentation.fragmentationLength[1], length); | 197 ASSERT_EQ(fragmentation.fragmentationLength[1], packet.payload_size()); |
203 VerifySingleNaluPayload(fragmentation, 1, frame, kFrameSize, packet, length); | 198 VerifySingleNaluPayload(fragmentation, 1, frame, packet.payload()); |
204 EXPECT_TRUE(last); | 199 EXPECT_TRUE(last); |
205 | 200 |
206 EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last)); | 201 EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
207 } | 202 } |
208 | 203 |
209 TEST(RtpPacketizerH264Test, TestStapA) { | 204 TEST(RtpPacketizerH264Test, TestStapA) { |
210 const size_t kFrameSize = | 205 const size_t kFrameSize = |
211 kMaxPayloadSize - 3 * kLengthFieldLength - kNalHeaderSize; | 206 kMaxPayloadSize - 3 * kLengthFieldLength - kNalHeaderSize; |
212 uint8_t frame[kFrameSize] = {0x07, 0xFF, // F=0, NRI=0, Type=7 (SPS). | 207 uint8_t frame[kFrameSize] = {0x07, 0xFF, // F=0, NRI=0, Type=7 (SPS). |
213 0x08, 0xFF, // F=0, NRI=0, Type=8 (PPS). | 208 0x08, 0xFF, // F=0, NRI=0, Type=8 (PPS). |
214 0x05}; // F=0, NRI=0, Type=5 (IDR). | 209 0x05}; // F=0, NRI=0, Type=5 (IDR). |
215 const size_t kPayloadOffset = 5; | 210 const size_t kPayloadOffset = 5; |
216 for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i) | 211 for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i) |
217 frame[i + kPayloadOffset] = i; | 212 frame[i + kPayloadOffset] = i; |
218 RTPFragmentationHeader fragmentation; | 213 RTPFragmentationHeader fragmentation; |
219 fragmentation.VerifyAndAllocateFragmentationHeader(3); | 214 fragmentation.VerifyAndAllocateFragmentationHeader(3); |
220 fragmentation.fragmentationOffset[0] = 0; | 215 fragmentation.fragmentationOffset[0] = 0; |
221 fragmentation.fragmentationLength[0] = 2; | 216 fragmentation.fragmentationLength[0] = 2; |
222 fragmentation.fragmentationOffset[1] = 2; | 217 fragmentation.fragmentationOffset[1] = 2; |
223 fragmentation.fragmentationLength[1] = 2; | 218 fragmentation.fragmentationLength[1] = 2; |
224 fragmentation.fragmentationOffset[2] = 4; | 219 fragmentation.fragmentationOffset[2] = 4; |
225 fragmentation.fragmentationLength[2] = | 220 fragmentation.fragmentationLength[2] = |
226 kNalHeaderSize + kFrameSize - kPayloadOffset; | 221 kNalHeaderSize + kFrameSize - kPayloadOffset; |
227 std::unique_ptr<RtpPacketizer> packetizer( | 222 std::unique_ptr<RtpPacketizer> packetizer( |
228 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); | 223 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); |
229 packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); | 224 packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
230 | 225 |
231 uint8_t packet[kMaxPayloadSize] = {0}; | 226 RtpPacketToSend packet(kNoExtensions); |
232 size_t length = 0; | 227 ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
233 bool last = false; | 228 bool last = false; |
234 ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last)); | 229 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
235 size_t expected_packet_size = | 230 size_t expected_packet_size = |
236 kNalHeaderSize + 3 * kLengthFieldLength + kFrameSize; | 231 kNalHeaderSize + 3 * kLengthFieldLength + kFrameSize; |
237 ASSERT_EQ(expected_packet_size, length); | 232 ASSERT_EQ(expected_packet_size, packet.payload_size()); |
238 EXPECT_TRUE(last); | 233 EXPECT_TRUE(last); |
239 for (size_t i = 0; i < fragmentation.fragmentationVectorSize; ++i) | 234 for (size_t i = 0; i < fragmentation.fragmentationVectorSize; ++i) |
240 VerifyStapAPayload(fragmentation, 0, i, frame, kFrameSize, packet, length); | 235 VerifyStapAPayload(fragmentation, 0, i, frame, packet.payload()); |
241 | 236 |
242 EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last)); | 237 EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
243 } | 238 } |
244 | 239 |
245 TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) { | 240 TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) { |
246 const size_t kFrameSize = kMaxPayloadSize - 1; | 241 const size_t kFrameSize = kMaxPayloadSize - 1; |
247 uint8_t frame[kFrameSize] = {0x07, 0xFF, // F=0, NRI=0, Type=7. | 242 uint8_t frame[kFrameSize] = {0x07, 0xFF, // F=0, NRI=0, Type=7. |
248 0x08, 0xFF, // F=0, NRI=0, Type=8. | 243 0x08, 0xFF, // F=0, NRI=0, Type=8. |
249 0x05}; // F=0, NRI=0, Type=5. | 244 0x05}; // F=0, NRI=0, Type=5. |
250 const size_t kPayloadOffset = 5; | 245 const size_t kPayloadOffset = 5; |
251 for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i) | 246 for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i) |
252 frame[i + kPayloadOffset] = i; | 247 frame[i + kPayloadOffset] = i; |
253 RTPFragmentationHeader fragmentation; | 248 RTPFragmentationHeader fragmentation; |
254 fragmentation.VerifyAndAllocateFragmentationHeader(3); | 249 fragmentation.VerifyAndAllocateFragmentationHeader(3); |
255 fragmentation.fragmentationOffset[0] = 0; | 250 fragmentation.fragmentationOffset[0] = 0; |
256 fragmentation.fragmentationLength[0] = 2; | 251 fragmentation.fragmentationLength[0] = 2; |
257 fragmentation.fragmentationOffset[1] = 2; | 252 fragmentation.fragmentationOffset[1] = 2; |
258 fragmentation.fragmentationLength[1] = 2; | 253 fragmentation.fragmentationLength[1] = 2; |
259 fragmentation.fragmentationOffset[2] = 4; | 254 fragmentation.fragmentationOffset[2] = 4; |
260 fragmentation.fragmentationLength[2] = | 255 fragmentation.fragmentationLength[2] = |
261 kNalHeaderSize + kFrameSize - kPayloadOffset; | 256 kNalHeaderSize + kFrameSize - kPayloadOffset; |
262 std::unique_ptr<RtpPacketizer> packetizer( | 257 std::unique_ptr<RtpPacketizer> packetizer( |
263 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); | 258 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); |
264 packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); | 259 packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
265 | 260 |
266 uint8_t packet[kMaxPayloadSize] = {0}; | 261 RtpPacketToSend packet(kNoExtensions); |
267 size_t length = 0; | 262 ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
268 bool last = false; | 263 bool last = false; |
269 ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last)); | 264 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
270 size_t expected_packet_size = kNalHeaderSize; | 265 size_t expected_packet_size = kNalHeaderSize; |
271 for (size_t i = 0; i < 2; ++i) { | 266 for (size_t i = 0; i < 2; ++i) { |
272 expected_packet_size += | 267 expected_packet_size += |
273 kLengthFieldLength + fragmentation.fragmentationLength[i]; | 268 kLengthFieldLength + fragmentation.fragmentationLength[i]; |
274 } | 269 } |
275 ASSERT_EQ(expected_packet_size, length); | 270 ASSERT_EQ(expected_packet_size, packet.payload_size()); |
276 EXPECT_FALSE(last); | 271 EXPECT_FALSE(last); |
277 for (size_t i = 0; i < 2; ++i) | 272 for (size_t i = 0; i < 2; ++i) |
278 VerifyStapAPayload(fragmentation, 0, i, frame, kFrameSize, packet, length); | 273 VerifyStapAPayload(fragmentation, 0, i, frame, packet.payload()); |
279 | 274 |
280 ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last)); | 275 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
281 expected_packet_size = fragmentation.fragmentationLength[2]; | 276 expected_packet_size = fragmentation.fragmentationLength[2]; |
282 ASSERT_EQ(expected_packet_size, length); | 277 ASSERT_EQ(expected_packet_size, packet.payload_size()); |
283 EXPECT_TRUE(last); | 278 EXPECT_TRUE(last); |
284 VerifySingleNaluPayload(fragmentation, 2, frame, kFrameSize, packet, length); | 279 VerifySingleNaluPayload(fragmentation, 2, frame, packet.payload()); |
285 | 280 |
286 EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last)); | 281 EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
287 } | 282 } |
288 | 283 |
289 TEST(RtpPacketizerH264Test, TestMixedStapA_FUA) { | 284 TEST(RtpPacketizerH264Test, TestMixedStapA_FUA) { |
290 const size_t kFuaNaluSize = 2 * (kMaxPayloadSize - 100); | 285 const size_t kFuaNaluSize = 2 * (kMaxPayloadSize - 100); |
291 const size_t kStapANaluSize = 100; | 286 const size_t kStapANaluSize = 100; |
292 RTPFragmentationHeader fragmentation; | 287 RTPFragmentationHeader fragmentation; |
293 fragmentation.VerifyAndAllocateFragmentationHeader(3); | 288 fragmentation.VerifyAndAllocateFragmentationHeader(3); |
294 fragmentation.fragmentationOffset[0] = 0; | 289 fragmentation.fragmentationOffset[0] = 0; |
295 fragmentation.fragmentationLength[0] = kFuaNaluSize; | 290 fragmentation.fragmentationLength[0] = kFuaNaluSize; |
296 fragmentation.fragmentationOffset[1] = kFuaNaluSize; | 291 fragmentation.fragmentationOffset[1] = kFuaNaluSize; |
(...skipping 11 matching lines...) Expand all Loading... |
308 } | 303 } |
309 } | 304 } |
310 std::unique_ptr<RtpPacketizer> packetizer( | 305 std::unique_ptr<RtpPacketizer> packetizer( |
311 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); | 306 RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame)); |
312 packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); | 307 packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); |
313 | 308 |
314 // First expecting two FU-A packets. | 309 // First expecting two FU-A packets. |
315 std::vector<size_t> fua_sizes; | 310 std::vector<size_t> fua_sizes; |
316 fua_sizes.push_back(1100); | 311 fua_sizes.push_back(1100); |
317 fua_sizes.push_back(1099); | 312 fua_sizes.push_back(1099); |
318 uint8_t packet[kMaxPayloadSize] = {0}; | 313 RtpPacketToSend packet(kNoExtensions); |
319 size_t length = 0; | 314 ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); |
320 bool last = false; | 315 bool last = false; |
321 int fua_offset = kNalHeaderSize; | 316 int fua_offset = kNalHeaderSize; |
322 for (size_t i = 0; i < 2; ++i) { | 317 for (size_t i = 0; i < 2; ++i) { |
323 ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last)); | 318 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
324 VerifyFua(i, frame, fua_offset, packet, length, fua_sizes); | 319 VerifyFua(i, frame, fua_offset, packet.payload(), fua_sizes); |
325 EXPECT_FALSE(last); | 320 EXPECT_FALSE(last); |
326 fua_offset += fua_sizes[i]; | 321 fua_offset += fua_sizes[i]; |
327 } | 322 } |
328 // Then expecting one STAP-A packet with two nal units. | 323 // Then expecting one STAP-A packet with two nal units. |
329 ASSERT_TRUE(packetizer->NextPacket(packet, &length, &last)); | 324 ASSERT_TRUE(packetizer->NextPacket(&packet, &last)); |
330 size_t expected_packet_size = | 325 size_t expected_packet_size = |
331 kNalHeaderSize + 2 * kLengthFieldLength + 2 * kStapANaluSize; | 326 kNalHeaderSize + 2 * kLengthFieldLength + 2 * kStapANaluSize; |
332 ASSERT_EQ(expected_packet_size, length); | 327 ASSERT_EQ(expected_packet_size, packet.payload_size()); |
333 EXPECT_TRUE(last); | 328 EXPECT_TRUE(last); |
334 for (size_t i = 1; i < fragmentation.fragmentationVectorSize; ++i) | 329 for (size_t i = 1; i < fragmentation.fragmentationVectorSize; ++i) |
335 VerifyStapAPayload(fragmentation, 1, i, frame, kFrameSize, packet, length); | 330 VerifyStapAPayload(fragmentation, 1, i, frame, packet.payload()); |
336 | 331 |
337 EXPECT_FALSE(packetizer->NextPacket(packet, &length, &last)); | 332 EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); |
338 } | 333 } |
339 | 334 |
340 TEST(RtpPacketizerH264Test, TestFUAOddSize) { | 335 TEST(RtpPacketizerH264Test, TestFUAOddSize) { |
341 const size_t kExpectedPayloadSizes[2] = {600, 600}; | 336 const size_t kExpectedPayloadSizes[2] = {600, 600}; |
342 TestFua( | 337 TestFua( |
343 kMaxPayloadSize + 1, | 338 kMaxPayloadSize + 1, |
344 kMaxPayloadSize, | 339 kMaxPayloadSize, |
345 std::vector<size_t>(kExpectedPayloadSizes, | 340 std::vector<size_t>(kExpectedPayloadSizes, |
346 kExpectedPayloadSizes + | 341 kExpectedPayloadSizes + |
347 sizeof(kExpectedPayloadSizes) / sizeof(size_t))); | 342 sizeof(kExpectedPayloadSizes) / sizeof(size_t))); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 | 417 |
423 // Set size to fragment SPS into two FU-A packets. | 418 // Set size to fragment SPS into two FU-A packets. |
424 packetizer_.reset(RtpPacketizer::Create( | 419 packetizer_.reset(RtpPacketizer::Create( |
425 kRtpVideoH264, sizeof(kOriginalSps) - 2 + kHeaderOverhead, nullptr, | 420 kRtpVideoH264, sizeof(kOriginalSps) - 2 + kHeaderOverhead, nullptr, |
426 kEmptyFrame)); | 421 kEmptyFrame)); |
427 | 422 |
428 packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(), | 423 packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(), |
429 &fragmentation_header_); | 424 &fragmentation_header_); |
430 | 425 |
431 bool last_packet = true; | 426 bool last_packet = true; |
432 uint8_t buffer[sizeof(kOriginalSps) + kHeaderOverhead] = {}; | 427 RtpPacketToSend packet(kNoExtensions); |
433 size_t num_bytes = 0; | 428 ASSERT_LE(sizeof(kOriginalSps) + kHeaderOverhead, packet.FreeCapacity()); |
434 | 429 |
435 EXPECT_TRUE(packetizer_->NextPacket(buffer, &num_bytes, &last_packet)); | 430 EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet)); |
436 size_t offset = H264::kNaluTypeSize; | 431 size_t offset = H264::kNaluTypeSize; |
437 size_t length = num_bytes - kFuAHeaderSize; | 432 size_t length = packet.payload_size() - kFuAHeaderSize; |
438 std::vector<uint8_t> expected_payload(&kRewrittenSps[offset], | 433 EXPECT_THAT(packet.payload().subview(kFuAHeaderSize), |
439 &kRewrittenSps[offset + length]); | 434 ElementsAreArray(&kRewrittenSps[offset], length)); |
440 EXPECT_THAT(expected_payload, | |
441 ::testing::ElementsAreArray(&buffer[kFuAHeaderSize], length)); | |
442 offset += length; | 435 offset += length; |
443 | 436 |
444 EXPECT_TRUE(packetizer_->NextPacket(buffer, &num_bytes, &last_packet)); | 437 EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet)); |
445 length = num_bytes - kFuAHeaderSize; | 438 length = packet.payload_size() - kFuAHeaderSize; |
446 expected_payload = std::vector<uint8_t>(&kRewrittenSps[offset], | 439 EXPECT_THAT(packet.payload().subview(kFuAHeaderSize), |
447 &kRewrittenSps[offset + length]); | 440 ElementsAreArray(&kRewrittenSps[offset], length)); |
448 EXPECT_THAT(expected_payload, | |
449 ::testing::ElementsAreArray(&buffer[kFuAHeaderSize], length)); | |
450 offset += length; | 441 offset += length; |
451 | 442 |
452 EXPECT_EQ(offset, sizeof(kRewrittenSps)); | 443 EXPECT_EQ(offset, sizeof(kRewrittenSps)); |
453 } | 444 } |
454 | 445 |
455 TEST_F(RtpPacketizerH264TestSpsRewriting, StapASps) { | 446 TEST_F(RtpPacketizerH264TestSpsRewriting, StapASps) { |
456 const size_t kHeaderOverhead = kFuAHeaderSize + 1; | 447 const size_t kHeaderOverhead = kFuAHeaderSize + 1; |
457 const size_t kExpectedTotalSize = H264::kNaluTypeSize + // Stap-A type. | 448 const size_t kExpectedTotalSize = H264::kNaluTypeSize + // Stap-A type. |
458 sizeof(kRewrittenSps) + sizeof(kIdrOne) + | 449 sizeof(kRewrittenSps) + sizeof(kIdrOne) + |
459 sizeof(kIdrTwo) + (kLengthFieldLength * 3); | 450 sizeof(kIdrTwo) + (kLengthFieldLength * 3); |
460 | 451 |
461 // Set size to include SPS and the rest of the packets in a Stap-A package. | 452 // Set size to include SPS and the rest of the packets in a Stap-A package. |
462 packetizer_.reset(RtpPacketizer::Create(kRtpVideoH264, | 453 packetizer_.reset(RtpPacketizer::Create(kRtpVideoH264, |
463 kExpectedTotalSize + kHeaderOverhead, | 454 kExpectedTotalSize + kHeaderOverhead, |
464 nullptr, kEmptyFrame)); | 455 nullptr, kEmptyFrame)); |
465 | 456 |
466 packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(), | 457 packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(), |
467 &fragmentation_header_); | 458 &fragmentation_header_); |
468 | 459 |
469 bool last_packet = true; | 460 bool last_packet = true; |
470 uint8_t buffer[kExpectedTotalSize + kHeaderOverhead] = {}; | 461 RtpPacketToSend packet(kNoExtensions); |
471 size_t num_bytes = 0; | 462 ASSERT_LE(kExpectedTotalSize + kHeaderOverhead, packet.FreeCapacity()); |
472 | 463 |
473 EXPECT_TRUE(packetizer_->NextPacket(buffer, &num_bytes, &last_packet)); | 464 EXPECT_TRUE(packetizer_->NextPacket(&packet, &last_packet)); |
474 EXPECT_EQ(kExpectedTotalSize, num_bytes); | 465 EXPECT_EQ(kExpectedTotalSize, packet.payload_size()); |
475 | 466 EXPECT_THAT(packet.payload().subview(H264::kNaluTypeSize + kLengthFieldLength, |
476 std::vector<uint8_t> expected_payload(kRewrittenSps, | 467 sizeof(kRewrittenSps)), |
477 &kRewrittenSps[sizeof(kRewrittenSps)]); | 468 ElementsAreArray(kRewrittenSps)); |
478 EXPECT_THAT(expected_payload, | |
479 ::testing::ElementsAreArray( | |
480 &buffer[H264::kNaluTypeSize + kLengthFieldLength], | |
481 sizeof(kRewrittenSps))); | |
482 } | 469 } |
483 | 470 |
484 class RtpDepacketizerH264Test : public ::testing::Test { | 471 class RtpDepacketizerH264Test : public ::testing::Test { |
485 protected: | 472 protected: |
486 RtpDepacketizerH264Test() | 473 RtpDepacketizerH264Test() |
487 : depacketizer_(RtpDepacketizer::Create(kRtpVideoH264)) {} | 474 : depacketizer_(RtpDepacketizer::Create(kRtpVideoH264)) {} |
488 | 475 |
489 void ExpectPacket(RtpDepacketizer::ParsedPayload* parsed_payload, | 476 void ExpectPacket(RtpDepacketizer::ParsedPayload* parsed_payload, |
490 const uint8_t* data, | 477 const uint8_t* data, |
491 size_t length) { | 478 size_t length) { |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 const RTPVideoHeaderH264& h264 = payload.type.Video.codecHeader.H264; | 818 const RTPVideoHeaderH264& h264 = payload.type.Video.codecHeader.H264; |
832 EXPECT_EQ(kH264SingleNalu, h264.packetization_type); | 819 EXPECT_EQ(kH264SingleNalu, h264.packetization_type); |
833 EXPECT_EQ(kSei, h264.nalu_type); | 820 EXPECT_EQ(kSei, h264.nalu_type); |
834 ASSERT_EQ(1u, h264.nalus_length); | 821 ASSERT_EQ(1u, h264.nalus_length); |
835 EXPECT_EQ(static_cast<H264::NaluType>(kSei), h264.nalus[0].type); | 822 EXPECT_EQ(static_cast<H264::NaluType>(kSei), h264.nalus[0].type); |
836 EXPECT_EQ(-1, h264.nalus[0].sps_id); | 823 EXPECT_EQ(-1, h264.nalus[0].sps_id); |
837 EXPECT_EQ(-1, h264.nalus[0].pps_id); | 824 EXPECT_EQ(-1, h264.nalus[0].pps_id); |
838 } | 825 } |
839 | 826 |
840 } // namespace webrtc | 827 } // namespace webrtc |
OLD | NEW |