1 /*
2  *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3  *
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
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h"
12 
13 #include <cstdint>
14 #include <vector>
15 
16 #include "absl/types/optional.h"
17 #include "api/array_view.h"
18 #include "common_video/h264/h264_common.h"
19 #include "modules/include/module_common_types.h"
20 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
21 #include "modules/rtp_rtcp/source/byte_io.h"
22 #include "rtc_base/copy_on_write_buffer.h"
23 #include "test/gmock.h"
24 #include "test/gtest.h"
25 
26 namespace webrtc {
27 namespace {
28 
29 using ::testing::Each;
30 using ::testing::ElementsAre;
31 using ::testing::ElementsAreArray;
32 using ::testing::Eq;
33 using ::testing::IsEmpty;
34 using ::testing::SizeIs;
35 
36 enum Nalu {
37   kSlice = 1,
38   kIdr = 5,
39   kSei = 6,
40   kSps = 7,
41   kPps = 8,
42   kStapA = 24,
43   kFuA = 28
44 };
45 
46 // Bit masks for FU (A and B) indicators.
47 enum NalDefs { kFBit = 0x80, kNriMask = 0x60, kTypeMask = 0x1F };
48 
49 // Bit masks for FU (A and B) headers.
50 enum FuDefs { kSBit = 0x80, kEBit = 0x40, kRBit = 0x20 };
51 
52 constexpr uint8_t kOriginalSps[] = {kSps, 0x00, 0x00, 0x03, 0x03,
53                                     0xF4, 0x05, 0x03, 0xC7, 0xC0};
54 constexpr uint8_t kRewrittenSps[] = {kSps, 0x00, 0x00, 0x03, 0x03,
55                                      0xF4, 0x05, 0x03, 0xC7, 0xE0,
56                                      0x1B, 0x41, 0x10, 0x8D, 0x00};
57 constexpr uint8_t kIdrOne[] = {kIdr, 0xFF, 0x00, 0x00, 0x04};
58 constexpr uint8_t kIdrTwo[] = {kIdr, 0xFF, 0x00, 0x11};
59 
TEST(VideoRtpDepacketizerH264Test,SingleNalu)60 TEST(VideoRtpDepacketizerH264Test, SingleNalu) {
61   uint8_t packet[2] = {0x05, 0xFF};  // F=0, NRI=0, Type=5 (IDR).
62   rtc::CopyOnWriteBuffer rtp_payload(packet);
63 
64   VideoRtpDepacketizerH264 depacketizer;
65   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
66       depacketizer.Parse(rtp_payload);
67   ASSERT_TRUE(parsed);
68 
69   EXPECT_EQ(parsed->video_payload, rtp_payload);
70   EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
71   EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
72   EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
73   const RTPVideoHeaderH264& h264 =
74       absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
75   EXPECT_EQ(h264.packetization_type, kH264SingleNalu);
76   EXPECT_EQ(h264.nalu_type, kIdr);
77 }
78 
TEST(VideoRtpDepacketizerH264Test,SingleNaluSpsWithResolution)79 TEST(VideoRtpDepacketizerH264Test, SingleNaluSpsWithResolution) {
80   uint8_t packet[] = {kSps, 0x7A, 0x00, 0x1F, 0xBC, 0xD9, 0x40, 0x50,
81                       0x05, 0xBA, 0x10, 0x00, 0x00, 0x03, 0x00, 0xC0,
82                       0x00, 0x00, 0x03, 0x2A, 0xE0, 0xF1, 0x83, 0x25};
83   rtc::CopyOnWriteBuffer rtp_payload(packet);
84 
85   VideoRtpDepacketizerH264 depacketizer;
86   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
87       depacketizer.Parse(rtp_payload);
88   ASSERT_TRUE(parsed);
89 
90   EXPECT_EQ(parsed->video_payload, rtp_payload);
91   EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
92   EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
93   EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
94   EXPECT_EQ(parsed->video_header.width, 1280u);
95   EXPECT_EQ(parsed->video_header.height, 720u);
96   const auto& h264 =
97       absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
98   EXPECT_EQ(h264.packetization_type, kH264SingleNalu);
99 }
100 
TEST(VideoRtpDepacketizerH264Test,StapAKey)101 TEST(VideoRtpDepacketizerH264Test, StapAKey) {
102   // clang-format off
103   const NaluInfo kExpectedNalus[] = { {H264::kSps, 0, -1},
104                                       {H264::kPps, 1, 2},
105                                       {H264::kIdr, -1, 0} };
106   uint8_t packet[] = {kStapA,  // F=0, NRI=0, Type=24.
107                       // Length, nal header, payload.
108                       0, 0x18, kExpectedNalus[0].type,
109                         0x7A, 0x00, 0x1F, 0xBC, 0xD9, 0x40, 0x50, 0x05, 0xBA,
110                         0x10, 0x00, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x03,
111                         0x2A, 0xE0, 0xF1, 0x83, 0x25,
112                       0, 0xD, kExpectedNalus[1].type,
113                         0x69, 0xFC, 0x0, 0x0, 0x3, 0x0, 0x7, 0xFF, 0xFF, 0xFF,
114                         0xF6, 0x40,
115                       0, 0xB, kExpectedNalus[2].type,
116                         0x85, 0xB8, 0x0, 0x4, 0x0, 0x0, 0x13, 0x93, 0x12, 0x0};
117   // clang-format on
118   rtc::CopyOnWriteBuffer rtp_payload(packet);
119 
120   VideoRtpDepacketizerH264 depacketizer;
121   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
122       depacketizer.Parse(rtp_payload);
123   ASSERT_TRUE(parsed);
124 
125   EXPECT_EQ(parsed->video_payload, rtp_payload);
126   EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
127   EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
128   EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
129   const auto& h264 =
130       absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
131   EXPECT_EQ(h264.packetization_type, kH264StapA);
132   // NALU type for aggregated packets is the type of the first packet only.
133   EXPECT_EQ(h264.nalu_type, kSps);
134   ASSERT_EQ(h264.nalus_length, 3u);
135   for (size_t i = 0; i < h264.nalus_length; ++i) {
136     EXPECT_EQ(h264.nalus[i].type, kExpectedNalus[i].type)
137         << "Failed parsing nalu " << i;
138     EXPECT_EQ(h264.nalus[i].sps_id, kExpectedNalus[i].sps_id)
139         << "Failed parsing nalu " << i;
140     EXPECT_EQ(h264.nalus[i].pps_id, kExpectedNalus[i].pps_id)
141         << "Failed parsing nalu " << i;
142   }
143 }
144 
TEST(VideoRtpDepacketizerH264Test,StapANaluSpsWithResolution)145 TEST(VideoRtpDepacketizerH264Test, StapANaluSpsWithResolution) {
146   uint8_t packet[] = {kStapA,  // F=0, NRI=0, Type=24.
147                                // Length (2 bytes), nal header, payload.
148                       0x00, 0x19, kSps, 0x7A, 0x00, 0x1F, 0xBC, 0xD9, 0x40,
149                       0x50, 0x05, 0xBA, 0x10, 0x00, 0x00, 0x03, 0x00, 0xC0,
150                       0x00, 0x00, 0x03, 0x2A, 0xE0, 0xF1, 0x83, 0x25, 0x80,
151                       0x00, 0x03, kIdr, 0xFF, 0x00, 0x00, 0x04, kIdr, 0xFF,
152                       0x00, 0x11};
153   rtc::CopyOnWriteBuffer rtp_payload(packet);
154 
155   VideoRtpDepacketizerH264 depacketizer;
156   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
157       depacketizer.Parse(rtp_payload);
158   ASSERT_TRUE(parsed);
159 
160   EXPECT_EQ(parsed->video_payload, rtp_payload);
161   EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
162   EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
163   EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
164   EXPECT_EQ(parsed->video_header.width, 1280u);
165   EXPECT_EQ(parsed->video_header.height, 720u);
166   const auto& h264 =
167       absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
168   EXPECT_EQ(h264.packetization_type, kH264StapA);
169 }
170 
TEST(VideoRtpDepacketizerH264Test,EmptyStapARejected)171 TEST(VideoRtpDepacketizerH264Test, EmptyStapARejected) {
172   uint8_t lone_empty_packet[] = {kStapA, 0x00, 0x00};
173   uint8_t leading_empty_packet[] = {kStapA, 0x00, 0x00, 0x00, 0x04,
174                                     kIdr,   0xFF, 0x00, 0x11};
175   uint8_t middle_empty_packet[] = {kStapA, 0x00, 0x03, kIdr, 0xFF, 0x00, 0x00,
176                                    0x00,   0x00, 0x04, kIdr, 0xFF, 0x00, 0x11};
177   uint8_t trailing_empty_packet[] = {kStapA, 0x00, 0x03, kIdr,
178                                      0xFF,   0x00, 0x00, 0x00};
179 
180   VideoRtpDepacketizerH264 depacketizer;
181   EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(lone_empty_packet)));
182   EXPECT_FALSE(
183       depacketizer.Parse(rtc::CopyOnWriteBuffer(leading_empty_packet)));
184   EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(middle_empty_packet)));
185   EXPECT_FALSE(
186       depacketizer.Parse(rtc::CopyOnWriteBuffer(trailing_empty_packet)));
187 }
188 
TEST(VideoRtpDepacketizerH264Test,DepacketizeWithRewriting)189 TEST(VideoRtpDepacketizerH264Test, DepacketizeWithRewriting) {
190   rtc::CopyOnWriteBuffer in_buffer;
191   rtc::Buffer out_buffer;
192 
193   uint8_t kHeader[2] = {kStapA};
194   in_buffer.AppendData(kHeader, 1);
195   out_buffer.AppendData(kHeader, 1);
196 
197   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kOriginalSps));
198   in_buffer.AppendData(kHeader, 2);
199   in_buffer.AppendData(kOriginalSps);
200   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kRewrittenSps));
201   out_buffer.AppendData(kHeader, 2);
202   out_buffer.AppendData(kRewrittenSps);
203 
204   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kIdrOne));
205   in_buffer.AppendData(kHeader, 2);
206   in_buffer.AppendData(kIdrOne);
207   out_buffer.AppendData(kHeader, 2);
208   out_buffer.AppendData(kIdrOne);
209 
210   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kIdrTwo));
211   in_buffer.AppendData(kHeader, 2);
212   in_buffer.AppendData(kIdrTwo);
213   out_buffer.AppendData(kHeader, 2);
214   out_buffer.AppendData(kIdrTwo);
215 
216   VideoRtpDepacketizerH264 depacketizer;
217   auto parsed = depacketizer.Parse(in_buffer);
218   ASSERT_TRUE(parsed);
219   EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
220                                  parsed->video_payload.size()),
221               ElementsAreArray(out_buffer));
222 }
223 
TEST(VideoRtpDepacketizerH264Test,DepacketizeWithDoubleRewriting)224 TEST(VideoRtpDepacketizerH264Test, DepacketizeWithDoubleRewriting) {
225   rtc::CopyOnWriteBuffer in_buffer;
226   rtc::Buffer out_buffer;
227 
228   uint8_t kHeader[2] = {kStapA};
229   in_buffer.AppendData(kHeader, 1);
230   out_buffer.AppendData(kHeader, 1);
231 
232   // First SPS will be kept...
233   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kOriginalSps));
234   in_buffer.AppendData(kHeader, 2);
235   in_buffer.AppendData(kOriginalSps);
236   out_buffer.AppendData(kHeader, 2);
237   out_buffer.AppendData(kOriginalSps);
238 
239   // ...only the second one will be rewritten.
240   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kOriginalSps));
241   in_buffer.AppendData(kHeader, 2);
242   in_buffer.AppendData(kOriginalSps);
243   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kRewrittenSps));
244   out_buffer.AppendData(kHeader, 2);
245   out_buffer.AppendData(kRewrittenSps);
246 
247   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kIdrOne));
248   in_buffer.AppendData(kHeader, 2);
249   in_buffer.AppendData(kIdrOne);
250   out_buffer.AppendData(kHeader, 2);
251   out_buffer.AppendData(kIdrOne);
252 
253   ByteWriter<uint16_t>::WriteBigEndian(kHeader, sizeof(kIdrTwo));
254   in_buffer.AppendData(kHeader, 2);
255   in_buffer.AppendData(kIdrTwo);
256   out_buffer.AppendData(kHeader, 2);
257   out_buffer.AppendData(kIdrTwo);
258 
259   VideoRtpDepacketizerH264 depacketizer;
260   auto parsed = depacketizer.Parse(in_buffer);
261   ASSERT_TRUE(parsed);
262   std::vector<uint8_t> expected_packet_payload(
263       out_buffer.data(), &out_buffer.data()[out_buffer.size()]);
264   EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
265                                  parsed->video_payload.size()),
266               ElementsAreArray(out_buffer));
267 }
268 
TEST(VideoRtpDepacketizerH264Test,StapADelta)269 TEST(VideoRtpDepacketizerH264Test, StapADelta) {
270   uint8_t packet[16] = {kStapA,  // F=0, NRI=0, Type=24.
271                                  // Length, nal header, payload.
272                         0, 0x02, kSlice, 0xFF, 0, 0x03, kSlice, 0xFF, 0x00, 0,
273                         0x04, kSlice, 0xFF, 0x00, 0x11};
274   rtc::CopyOnWriteBuffer rtp_payload(packet);
275 
276   VideoRtpDepacketizerH264 depacketizer;
277   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
278       depacketizer.Parse(rtp_payload);
279   ASSERT_TRUE(parsed);
280 
281   EXPECT_EQ(parsed->video_payload.size(), rtp_payload.size());
282   EXPECT_EQ(parsed->video_payload.cdata(), rtp_payload.cdata());
283 
284   EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameDelta);
285   EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
286   EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
287   const RTPVideoHeaderH264& h264 =
288       absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
289   EXPECT_EQ(h264.packetization_type, kH264StapA);
290   // NALU type for aggregated packets is the type of the first packet only.
291   EXPECT_EQ(h264.nalu_type, kSlice);
292 }
293 
TEST(VideoRtpDepacketizerH264Test,FuA)294 TEST(VideoRtpDepacketizerH264Test, FuA) {
295   // clang-format off
296   uint8_t packet1[] = {
297       kFuA,          // F=0, NRI=0, Type=28.
298       kSBit | kIdr,  // FU header.
299       0x85, 0xB8, 0x0, 0x4, 0x0, 0x0, 0x13, 0x93, 0x12, 0x0  // Payload.
300   };
301   // clang-format on
302   const uint8_t kExpected1[] = {kIdr, 0x85, 0xB8, 0x0,  0x4, 0x0,
303                                 0x0,  0x13, 0x93, 0x12, 0x0};
304 
305   uint8_t packet2[] = {
306       kFuA,  // F=0, NRI=0, Type=28.
307       kIdr,  // FU header.
308       0x02   // Payload.
309   };
310   const uint8_t kExpected2[] = {0x02};
311 
312   uint8_t packet3[] = {
313       kFuA,          // F=0, NRI=0, Type=28.
314       kEBit | kIdr,  // FU header.
315       0x03           // Payload.
316   };
317   const uint8_t kExpected3[] = {0x03};
318 
319   VideoRtpDepacketizerH264 depacketizer;
320   absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed1 =
321       depacketizer.Parse(rtc::CopyOnWriteBuffer(packet1));
322   ASSERT_TRUE(parsed1);
323   // We expect that the first packet is one byte shorter since the FU-A header
324   // has been replaced by the original nal header.
325   EXPECT_THAT(rtc::MakeArrayView(parsed1->video_payload.cdata(),
326                                  parsed1->video_payload.size()),
327               ElementsAreArray(kExpected1));
328   EXPECT_EQ(parsed1->video_header.frame_type, VideoFrameType::kVideoFrameKey);
329   EXPECT_EQ(parsed1->video_header.codec, kVideoCodecH264);
330   EXPECT_TRUE(parsed1->video_header.is_first_packet_in_frame);
331   {
332     const RTPVideoHeaderH264& h264 =
333         absl::get<RTPVideoHeaderH264>(parsed1->video_header.video_type_header);
334     EXPECT_EQ(h264.packetization_type, kH264FuA);
335     EXPECT_EQ(h264.nalu_type, kIdr);
336     ASSERT_EQ(h264.nalus_length, 1u);
337     EXPECT_EQ(h264.nalus[0].type, static_cast<H264::NaluType>(kIdr));
338     EXPECT_EQ(h264.nalus[0].sps_id, -1);
339     EXPECT_EQ(h264.nalus[0].pps_id, 0);
340   }
341 
342   // Following packets will be 2 bytes shorter since they will only be appended
343   // onto the first packet.
344   auto parsed2 = depacketizer.Parse(rtc::CopyOnWriteBuffer(packet2));
345   EXPECT_THAT(rtc::MakeArrayView(parsed2->video_payload.cdata(),
346                                  parsed2->video_payload.size()),
347               ElementsAreArray(kExpected2));
348   EXPECT_FALSE(parsed2->video_header.is_first_packet_in_frame);
349   EXPECT_EQ(parsed2->video_header.codec, kVideoCodecH264);
350   {
351     const RTPVideoHeaderH264& h264 =
352         absl::get<RTPVideoHeaderH264>(parsed2->video_header.video_type_header);
353     EXPECT_EQ(h264.packetization_type, kH264FuA);
354     EXPECT_EQ(h264.nalu_type, kIdr);
355     // NALU info is only expected for the first FU-A packet.
356     EXPECT_EQ(h264.nalus_length, 0u);
357   }
358 
359   auto parsed3 = depacketizer.Parse(rtc::CopyOnWriteBuffer(packet3));
360   EXPECT_THAT(rtc::MakeArrayView(parsed3->video_payload.cdata(),
361                                  parsed3->video_payload.size()),
362               ElementsAreArray(kExpected3));
363   EXPECT_FALSE(parsed3->video_header.is_first_packet_in_frame);
364   EXPECT_EQ(parsed3->video_header.codec, kVideoCodecH264);
365   {
366     const RTPVideoHeaderH264& h264 =
367         absl::get<RTPVideoHeaderH264>(parsed3->video_header.video_type_header);
368     EXPECT_EQ(h264.packetization_type, kH264FuA);
369     EXPECT_EQ(h264.nalu_type, kIdr);
370     // NALU info is only expected for the first FU-A packet.
371     ASSERT_EQ(h264.nalus_length, 0u);
372   }
373 }
374 
TEST(VideoRtpDepacketizerH264Test,EmptyPayload)375 TEST(VideoRtpDepacketizerH264Test, EmptyPayload) {
376   rtc::CopyOnWriteBuffer empty;
377   VideoRtpDepacketizerH264 depacketizer;
378   EXPECT_FALSE(depacketizer.Parse(empty));
379 }
380 
TEST(VideoRtpDepacketizerH264Test,TruncatedFuaNalu)381 TEST(VideoRtpDepacketizerH264Test, TruncatedFuaNalu) {
382   const uint8_t kPayload[] = {0x9c};
383   VideoRtpDepacketizerH264 depacketizer;
384   EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
385 }
386 
TEST(VideoRtpDepacketizerH264Test,TruncatedSingleStapANalu)387 TEST(VideoRtpDepacketizerH264Test, TruncatedSingleStapANalu) {
388   const uint8_t kPayload[] = {0xd8, 0x27};
389   VideoRtpDepacketizerH264 depacketizer;
390   EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
391 }
392 
TEST(VideoRtpDepacketizerH264Test,StapAPacketWithTruncatedNalUnits)393 TEST(VideoRtpDepacketizerH264Test, StapAPacketWithTruncatedNalUnits) {
394   const uint8_t kPayload[] = {0x58, 0xCB, 0xED, 0xDF};
395   VideoRtpDepacketizerH264 depacketizer;
396   EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
397 }
398 
TEST(VideoRtpDepacketizerH264Test,TruncationJustAfterSingleStapANalu)399 TEST(VideoRtpDepacketizerH264Test, TruncationJustAfterSingleStapANalu) {
400   const uint8_t kPayload[] = {0x38, 0x27, 0x27};
401   VideoRtpDepacketizerH264 depacketizer;
402   EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
403 }
404 
TEST(VideoRtpDepacketizerH264Test,ShortSpsPacket)405 TEST(VideoRtpDepacketizerH264Test, ShortSpsPacket) {
406   const uint8_t kPayload[] = {0x27, 0x80, 0x00};
407   VideoRtpDepacketizerH264 depacketizer;
408   EXPECT_TRUE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
409 }
410 
TEST(VideoRtpDepacketizerH264Test,SeiPacket)411 TEST(VideoRtpDepacketizerH264Test, SeiPacket) {
412   const uint8_t kPayload[] = {
413       kSei,                   // F=0, NRI=0, Type=6.
414       0x03, 0x03, 0x03, 0x03  // Payload.
415   };
416   VideoRtpDepacketizerH264 depacketizer;
417   auto parsed = depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload));
418   ASSERT_TRUE(parsed);
419   const RTPVideoHeaderH264& h264 =
420       absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
421   EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameDelta);
422   EXPECT_EQ(h264.packetization_type, kH264SingleNalu);
423   EXPECT_EQ(h264.nalu_type, kSei);
424   ASSERT_EQ(h264.nalus_length, 1u);
425   EXPECT_EQ(h264.nalus[0].type, static_cast<H264::NaluType>(kSei));
426   EXPECT_EQ(h264.nalus[0].sps_id, -1);
427   EXPECT_EQ(h264.nalus[0].pps_id, -1);
428 }
429 
430 }  // namespace
431 }  // namespace webrtc
432