blob: 3d2a432c547e9abc461a64617e5fe9e6b7eea643 [file] [log] [blame]
philipel10dc1a62021-09-15 10:45:43 +02001/*
2 * Copyright (c) 2021 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#include "modules/video_coding/h264_packet_buffer.h"
11
12#include <cstring>
13#include <limits>
14#include <ostream>
15#include <string>
16#include <utility>
17
18#include "api/array_view.h"
19#include "api/video/render_resolution.h"
20#include "common_video/h264/h264_common.h"
21#include "rtc_base/system/unused.h"
22#include "test/gmock.h"
23#include "test/gtest.h"
24
25namespace webrtc {
26namespace {
27
28using ::testing::ElementsAreArray;
29using ::testing::Eq;
30using ::testing::IsEmpty;
31using ::testing::SizeIs;
32
33using H264::NaluType::kAud;
34using H264::NaluType::kFuA;
35using H264::NaluType::kIdr;
36using H264::NaluType::kPps;
37using H264::NaluType::kSlice;
38using H264::NaluType::kSps;
39using H264::NaluType::kStapA;
40
41constexpr int kBufferSize = 2048;
42
43std::vector<uint8_t> StartCode() {
44 return {0, 0, 0, 1};
45}
46
47NaluInfo MakeNaluInfo(uint8_t type) {
48 NaluInfo res;
49 res.type = type;
50 res.sps_id = -1;
51 res.pps_id = -1;
52 return res;
53}
54
55class Packet {
56 public:
57 explicit Packet(H264PacketizationTypes type);
58
59 Packet& Idr(std::vector<uint8_t> payload = {9, 9, 9});
60 Packet& Slice(std::vector<uint8_t> payload = {9, 9, 9});
61 Packet& Sps(std::vector<uint8_t> payload = {9, 9, 9});
62 Packet& SpsWithResolution(RenderResolution resolution,
63 std::vector<uint8_t> payload = {9, 9, 9});
64 Packet& Pps(std::vector<uint8_t> payload = {9, 9, 9});
65 Packet& Aud();
66 Packet& Marker();
67 Packet& AsFirstFragment();
68 Packet& Time(uint32_t rtp_timestamp);
69 Packet& SeqNum(uint16_t rtp_seq_num);
70
71 std::unique_ptr<H264PacketBuffer::Packet> Build();
72
73 private:
74 rtc::CopyOnWriteBuffer BuildFuaPayload() const;
75 rtc::CopyOnWriteBuffer BuildSingleNaluPayload() const;
76 rtc::CopyOnWriteBuffer BuildStapAPayload() const;
77
78 RTPVideoHeaderH264& H264Header() {
79 return absl::get<RTPVideoHeaderH264>(video_header_.video_type_header);
80 }
81 const RTPVideoHeaderH264& H264Header() const {
82 return absl::get<RTPVideoHeaderH264>(video_header_.video_type_header);
83 }
84
85 H264PacketizationTypes type_;
86 RTPVideoHeader video_header_;
87 bool first_fragment_ = false;
88 bool marker_bit_ = false;
89 uint32_t rtp_timestamp_ = 0;
90 uint16_t rtp_seq_num_ = 0;
91 std::vector<std::vector<uint8_t>> nalu_payloads_;
92};
93
94Packet::Packet(H264PacketizationTypes type) : type_(type) {
95 video_header_.video_type_header.emplace<RTPVideoHeaderH264>();
96}
97
98Packet& Packet::Idr(std::vector<uint8_t> payload) {
99 auto& h264_header = H264Header();
100 h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kIdr);
101 nalu_payloads_.push_back(std::move(payload));
102 return *this;
103}
104
105Packet& Packet::Slice(std::vector<uint8_t> payload) {
106 auto& h264_header = H264Header();
107 h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSlice);
108 nalu_payloads_.push_back(std::move(payload));
109 return *this;
110}
111
112Packet& Packet::Sps(std::vector<uint8_t> payload) {
113 auto& h264_header = H264Header();
114 h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSps);
115 nalu_payloads_.push_back(std::move(payload));
116 return *this;
117}
118
119Packet& Packet::SpsWithResolution(RenderResolution resolution,
120 std::vector<uint8_t> payload) {
121 auto& h264_header = H264Header();
122 h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSps);
123 video_header_.width = resolution.Width();
124 video_header_.height = resolution.Height();
125 nalu_payloads_.push_back(std::move(payload));
126 return *this;
127}
128
129Packet& Packet::Pps(std::vector<uint8_t> payload) {
130 auto& h264_header = H264Header();
131 h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kPps);
132 nalu_payloads_.push_back(std::move(payload));
133 return *this;
134}
135
136Packet& Packet::Aud() {
137 auto& h264_header = H264Header();
138 h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kAud);
139 nalu_payloads_.push_back({});
140 return *this;
141}
142
143Packet& Packet::Marker() {
144 marker_bit_ = true;
145 return *this;
146}
147
148Packet& Packet::AsFirstFragment() {
149 first_fragment_ = true;
150 return *this;
151}
152
153Packet& Packet::Time(uint32_t rtp_timestamp) {
154 rtp_timestamp_ = rtp_timestamp;
155 return *this;
156}
157
158Packet& Packet::SeqNum(uint16_t rtp_seq_num) {
159 rtp_seq_num_ = rtp_seq_num;
160 return *this;
161}
162
163std::unique_ptr<H264PacketBuffer::Packet> Packet::Build() {
164 auto res = std::make_unique<H264PacketBuffer::Packet>();
165
166 auto& h264_header = H264Header();
167 switch (type_) {
168 case kH264FuA: {
169 RTC_CHECK_EQ(h264_header.nalus_length, 1);
170 res->video_payload = BuildFuaPayload();
171 break;
172 }
173 case kH264SingleNalu: {
174 RTC_CHECK_EQ(h264_header.nalus_length, 1);
175 res->video_payload = BuildSingleNaluPayload();
176 break;
177 }
178 case kH264StapA: {
179 RTC_CHECK_GT(h264_header.nalus_length, 1);
180 RTC_CHECK_LE(h264_header.nalus_length, kMaxNalusPerPacket);
181 res->video_payload = BuildStapAPayload();
182 break;
183 }
184 }
185
186 if (type_ == kH264FuA && !first_fragment_) {
187 h264_header.nalus_length = 0;
188 }
189
190 h264_header.packetization_type = type_;
191 res->marker_bit = marker_bit_;
192 res->video_header = video_header_;
193 res->timestamp = rtp_timestamp_;
194 res->seq_num = rtp_seq_num_;
195 res->video_header.codec = kVideoCodecH264;
196
197 return res;
198}
199
200rtc::CopyOnWriteBuffer Packet::BuildFuaPayload() const {
201 return rtc::CopyOnWriteBuffer(nalu_payloads_[0].data(),
202 nalu_payloads_[0].size());
203}
204
205rtc::CopyOnWriteBuffer Packet::BuildSingleNaluPayload() const {
206 rtc::CopyOnWriteBuffer res;
207 auto& h264_header = H264Header();
208 res.AppendData(&h264_header.nalus[0].type, 1);
209 res.AppendData(nalu_payloads_[0].data(), nalu_payloads_[0].size());
210 return res;
211}
212
213rtc::CopyOnWriteBuffer Packet::BuildStapAPayload() const {
214 rtc::CopyOnWriteBuffer res;
215
216 const uint8_t indicator = H264::NaluType::kStapA;
217 res.AppendData(&indicator, 1);
218
219 auto& h264_header = H264Header();
220 for (size_t i = 0; i < h264_header.nalus_length; ++i) {
221 // The two first bytes indicates the nalu segment size.
222 uint8_t length_as_array[2] = {
223 0, static_cast<uint8_t>(nalu_payloads_[i].size() + 1)};
224 res.AppendData(length_as_array);
225
226 res.AppendData(&h264_header.nalus[i].type, 1);
227 res.AppendData(nalu_payloads_[i].data(), nalu_payloads_[i].size());
228 }
229 return res;
230}
231
232rtc::ArrayView<const uint8_t> PacketPayload(
233 const std::unique_ptr<H264PacketBuffer::Packet>& packet) {
234 return packet->video_payload;
235}
236
237std::vector<uint8_t> FlatVector(
238 const std::vector<std::vector<uint8_t>>& elems) {
239 std::vector<uint8_t> res;
240 for (const auto& elem : elems) {
241 res.insert(res.end(), elem.begin(), elem.end());
242 }
243 return res;
244}
245
246TEST(H264PacketBufferTest, IdrIsKeyframe) {
247 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/true);
248
249 EXPECT_THAT(
250 packet_buffer.InsertPacket(Packet(kH264SingleNalu).Idr().Marker().Build())
251 .packets,
252 SizeIs(1));
253}
254
255TEST(H264PacketBufferTest, IdrIsNotKeyframe) {
256 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
257
258 EXPECT_THAT(
259 packet_buffer.InsertPacket(Packet(kH264SingleNalu).Idr().Marker().Build())
260 .packets,
261 IsEmpty());
262}
263
264TEST(H264PacketBufferTest, IdrIsKeyframeFuaRequiresFirstFragmet) {
265 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/true);
266
267 // Not marked as the first fragment
268 EXPECT_THAT(
269 packet_buffer
270 .InsertPacket(Packet(kH264FuA).Idr().SeqNum(0).Time(0).Build())
271 .packets,
272 IsEmpty());
273
274 EXPECT_THAT(packet_buffer
275 .InsertPacket(
276 Packet(kH264FuA).Idr().SeqNum(1).Time(0).Marker().Build())
277 .packets,
278 IsEmpty());
279
280 // Marked as first fragment
281 EXPECT_THAT(packet_buffer
282 .InsertPacket(Packet(kH264FuA)
283 .Idr()
284 .SeqNum(2)
285 .Time(1)
286 .AsFirstFragment()
287 .Build())
288 .packets,
289 IsEmpty());
290
291 EXPECT_THAT(packet_buffer
292 .InsertPacket(
293 Packet(kH264FuA).Idr().SeqNum(3).Time(1).Marker().Build())
294 .packets,
295 SizeIs(2));
296}
297
298TEST(H264PacketBufferTest, SpsPpsIdrIsKeyframeSingleNalus) {
299 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
300
301 RTC_UNUSED(packet_buffer.InsertPacket(
302 Packet(kH264SingleNalu).Sps().SeqNum(0).Time(0).Build()));
303 RTC_UNUSED(packet_buffer.InsertPacket(
304 Packet(kH264SingleNalu).Pps().SeqNum(1).Time(0).Build()));
305 EXPECT_THAT(
306 packet_buffer
307 .InsertPacket(
308 Packet(kH264SingleNalu).Idr().SeqNum(2).Time(0).Marker().Build())
309 .packets,
310 SizeIs(3));
311}
312
313TEST(H264PacketBufferTest, PpsIdrIsNotKeyframeSingleNalus) {
314 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
315
316 RTC_UNUSED(packet_buffer.InsertPacket(
317 Packet(kH264SingleNalu).Pps().SeqNum(0).Time(0).Build()));
318 EXPECT_THAT(
319 packet_buffer
320 .InsertPacket(
321 Packet(kH264SingleNalu).Idr().SeqNum(1).Time(0).Marker().Build())
322 .packets,
323 IsEmpty());
324}
325
326TEST(H264PacketBufferTest, SpsIdrIsNotKeyframeSingleNalus) {
327 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
328
329 RTC_UNUSED(packet_buffer.InsertPacket(
330 Packet(kH264SingleNalu).Sps().SeqNum(0).Time(0).Build()));
331 EXPECT_THAT(
332 packet_buffer
333 .InsertPacket(
334 Packet(kH264SingleNalu).Idr().SeqNum(1).Time(0).Marker().Build())
335 .packets,
336 IsEmpty());
337}
338
339TEST(H264PacketBufferTest, SpsPpsIdrIsKeyframeStapA) {
340 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
341
342 EXPECT_THAT(packet_buffer
343 .InsertPacket(Packet(kH264StapA)
344 .Sps()
345 .Pps()
346 .Idr()
347 .SeqNum(0)
348 .Time(0)
349 .Marker()
350 .Build())
351 .packets,
352 SizeIs(1));
353}
354
355TEST(H264PacketBufferTest, PpsIdrIsNotKeyframeStapA) {
356 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
357
358 EXPECT_THAT(
359 packet_buffer
360 .InsertPacket(
361 Packet(kH264StapA).Pps().Idr().SeqNum(0).Time(0).Marker().Build())
362 .packets,
363 IsEmpty());
364}
365
366TEST(H264PacketBufferTest, SpsIdrIsNotKeyframeStapA) {
367 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
368
369 EXPECT_THAT(
370 packet_buffer
371 .InsertPacket(
372 Packet(kH264StapA).Sps().Idr().SeqNum(2).Time(2).Marker().Build())
373 .packets,
374 IsEmpty());
375
376 EXPECT_THAT(packet_buffer
377 .InsertPacket(Packet(kH264StapA)
378 .Sps()
379 .Pps()
380 .Idr()
381 .SeqNum(3)
382 .Time(3)
383 .Marker()
384 .Build())
385 .packets,
386 SizeIs(1));
387}
388
389TEST(H264PacketBufferTest, InsertingSpsPpsLastCompletesKeyframe) {
390 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
391
392 RTC_UNUSED(packet_buffer.InsertPacket(
393 Packet(kH264SingleNalu).Idr().SeqNum(2).Time(1).Marker().Build()));
394
395 EXPECT_THAT(packet_buffer
396 .InsertPacket(
397 Packet(kH264StapA).Sps().Pps().SeqNum(1).Time(1).Build())
398 .packets,
399 SizeIs(2));
400}
401
402TEST(H264PacketBufferTest, InsertingMidFuaCompletesFrame) {
403 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
404
405 EXPECT_THAT(packet_buffer
406 .InsertPacket(Packet(kH264StapA)
407 .Sps()
408 .Pps()
409 .Idr()
410 .SeqNum(0)
411 .Time(0)
412 .Marker()
413 .Build())
414 .packets,
415 SizeIs(1));
416
417 RTC_UNUSED(packet_buffer.InsertPacket(
418 Packet(kH264FuA).Slice().SeqNum(1).Time(1).AsFirstFragment().Build()));
419 RTC_UNUSED(packet_buffer.InsertPacket(
420 Packet(kH264FuA).Slice().SeqNum(3).Time(1).Marker().Build()));
421 EXPECT_THAT(
422 packet_buffer
423 .InsertPacket(Packet(kH264FuA).Slice().SeqNum(2).Time(1).Build())
424 .packets,
425 SizeIs(3));
426}
427
428TEST(H264PacketBufferTest, SeqNumJumpDoesNotCompleteFrame) {
429 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
430
431 EXPECT_THAT(packet_buffer
432 .InsertPacket(Packet(kH264StapA)
433 .Sps()
434 .Pps()
435 .Idr()
436 .SeqNum(0)
437 .Time(0)
438 .Marker()
439 .Build())
440 .packets,
441 SizeIs(1));
442
443 EXPECT_THAT(
444 packet_buffer
445 .InsertPacket(Packet(kH264FuA).Slice().SeqNum(1).Time(1).Build())
446 .packets,
447 IsEmpty());
448
449 // Add `kBufferSize` to make the index of the sequence number wrap and end up
450 // where the packet with sequence number 2 would have ended up.
451 EXPECT_THAT(packet_buffer
452 .InsertPacket(Packet(kH264FuA)
453 .Slice()
454 .SeqNum(2 + kBufferSize)
455 .Time(3)
456 .Marker()
457 .Build())
458 .packets,
459 IsEmpty());
460}
461
462TEST(H264PacketBufferTest, OldFramesAreNotCompletedAfterBufferWrap) {
463 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
464
465 EXPECT_THAT(packet_buffer
466 .InsertPacket(Packet(kH264SingleNalu)
467 .Slice()
468 .SeqNum(1)
469 .Time(1)
470 .Marker()
471 .Build())
472 .packets,
473 IsEmpty());
474
475 // New keyframe, preceedes packet with sequence number 1 in the buffer.
476 EXPECT_THAT(packet_buffer
477 .InsertPacket(Packet(kH264StapA)
478 .Sps()
479 .Pps()
480 .Idr()
481 .SeqNum(kBufferSize)
482 .Time(kBufferSize)
483 .Marker()
484 .Build())
485 .packets,
486 SizeIs(1));
487}
488
489TEST(H264PacketBufferTest, OldPacketsDontBlockNewPackets) {
490 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
491 EXPECT_THAT(packet_buffer
492 .InsertPacket(Packet(kH264StapA)
493 .Sps()
494 .Pps()
495 .Idr()
496 .SeqNum(kBufferSize)
497 .Time(kBufferSize)
498 .Marker()
499 .Build())
500 .packets,
501 SizeIs(1));
502
503 RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
504 .Slice()
505 .SeqNum(kBufferSize + 1)
506 .Time(kBufferSize + 1)
507 .AsFirstFragment()
508 .Build()));
509
510 RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
511 .Slice()
512 .SeqNum(kBufferSize + 3)
513 .Time(kBufferSize + 1)
514 .Marker()
515 .Build()));
516 EXPECT_THAT(
517 packet_buffer
518 .InsertPacket(Packet(kH264FuA).Slice().SeqNum(2).Time(2).Build())
519 .packets,
520 IsEmpty());
521
522 EXPECT_THAT(packet_buffer
523 .InsertPacket(Packet(kH264FuA)
524 .Slice()
525 .SeqNum(kBufferSize + 2)
526 .Time(kBufferSize + 1)
527 .Build())
528 .packets,
529 SizeIs(3));
530}
531
532TEST(H264PacketBufferTest, OldPacketDoesntCompleteFrame) {
533 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
534
535 EXPECT_THAT(packet_buffer
536 .InsertPacket(Packet(kH264StapA)
537 .Sps()
538 .Pps()
539 .Idr()
540 .SeqNum(kBufferSize)
541 .Time(kBufferSize)
542 .Marker()
543 .Build())
544 .packets,
545 SizeIs(1));
546
547 EXPECT_THAT(packet_buffer
548 .InsertPacket(Packet(kH264FuA)
549 .Slice()
550 .SeqNum(kBufferSize + 3)
551 .Time(kBufferSize + 1)
552 .Marker()
553 .Build())
554 .packets,
555 IsEmpty());
556
557 EXPECT_THAT(
558 packet_buffer
559 .InsertPacket(
560 Packet(kH264FuA).Slice().SeqNum(2).Time(2).Marker().Build())
561 .packets,
562 IsEmpty());
563
564 EXPECT_THAT(packet_buffer
565 .InsertPacket(Packet(kH264FuA)
566 .Slice()
567 .SeqNum(kBufferSize + 1)
568 .Time(kBufferSize + 1)
569 .AsFirstFragment()
570 .Build())
571 .packets,
572 IsEmpty());
573}
574
575TEST(H264PacketBufferTest, FrameBoundariesAreSet) {
576 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
577
578 auto key = packet_buffer.InsertPacket(
579 Packet(kH264StapA).Sps().Pps().Idr().SeqNum(1).Time(1).Marker().Build());
580
581 ASSERT_THAT(key.packets, SizeIs(1));
582 EXPECT_TRUE(key.packets[0]->video_header.is_first_packet_in_frame);
583 EXPECT_TRUE(key.packets[0]->video_header.is_last_packet_in_frame);
584
585 RTC_UNUSED(packet_buffer.InsertPacket(
586 Packet(kH264FuA).Slice().SeqNum(2).Time(2).Build()));
587 RTC_UNUSED(packet_buffer.InsertPacket(
588 Packet(kH264FuA).Slice().SeqNum(3).Time(2).Build()));
589 auto delta = packet_buffer.InsertPacket(
590 Packet(kH264FuA).Slice().SeqNum(4).Time(2).Marker().Build());
591
592 ASSERT_THAT(delta.packets, SizeIs(3));
593 EXPECT_TRUE(delta.packets[0]->video_header.is_first_packet_in_frame);
594 EXPECT_FALSE(delta.packets[0]->video_header.is_last_packet_in_frame);
595
596 EXPECT_FALSE(delta.packets[1]->video_header.is_first_packet_in_frame);
597 EXPECT_FALSE(delta.packets[1]->video_header.is_last_packet_in_frame);
598
599 EXPECT_FALSE(delta.packets[2]->video_header.is_first_packet_in_frame);
600 EXPECT_TRUE(delta.packets[2]->video_header.is_last_packet_in_frame);
601}
602
603TEST(H264PacketBufferTest, ResolutionSetOnFirstPacket) {
604 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
605
606 RTC_UNUSED(packet_buffer.InsertPacket(
607 Packet(kH264SingleNalu).Aud().SeqNum(1).Time(1).Build()));
608 auto res = packet_buffer.InsertPacket(Packet(kH264StapA)
609 .SpsWithResolution({320, 240})
610 .Pps()
611 .Idr()
612 .SeqNum(2)
613 .Time(1)
614 .Marker()
615 .Build());
616
617 ASSERT_THAT(res.packets, SizeIs(2));
618 EXPECT_THAT(res.packets[0]->video_header.width, Eq(320));
619 EXPECT_THAT(res.packets[0]->video_header.height, Eq(240));
620}
621
622TEST(H264PacketBufferTest, KeyframeAndDeltaFrameSetOnFirstPacket) {
623 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
624
625 RTC_UNUSED(packet_buffer.InsertPacket(
626 Packet(kH264SingleNalu).Aud().SeqNum(1).Time(1).Build()));
627 auto key = packet_buffer.InsertPacket(
628 Packet(kH264StapA).Sps().Pps().Idr().SeqNum(2).Time(1).Marker().Build());
629
630 auto delta = packet_buffer.InsertPacket(
631 Packet(kH264SingleNalu).Slice().SeqNum(3).Time(2).Marker().Build());
632
633 ASSERT_THAT(key.packets, SizeIs(2));
634 EXPECT_THAT(key.packets[0]->video_header.frame_type,
635 Eq(VideoFrameType::kVideoFrameKey));
636 ASSERT_THAT(delta.packets, SizeIs(1));
637 EXPECT_THAT(delta.packets[0]->video_header.frame_type,
638 Eq(VideoFrameType::kVideoFrameDelta));
639}
640
641TEST(H264PacketBufferTest, RtpSeqNumWrap) {
642 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
643
644 RTC_UNUSED(packet_buffer.InsertPacket(
645 Packet(kH264StapA).Sps().Pps().SeqNum(0xffff).Time(0).Build()));
646
647 RTC_UNUSED(packet_buffer.InsertPacket(
648 Packet(kH264FuA).Idr().SeqNum(0).Time(0).Build()));
649 EXPECT_THAT(packet_buffer
650 .InsertPacket(
651 Packet(kH264FuA).Idr().SeqNum(1).Time(0).Marker().Build())
652 .packets,
653 SizeIs(3));
654}
655
656TEST(H264PacketBufferTest, StapAFixedBitstream) {
657 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
658
659 auto packets = packet_buffer
660 .InsertPacket(Packet(kH264StapA)
661 .Sps({1, 2, 3})
662 .Pps({4, 5, 6})
663 .Idr({7, 8, 9})
664 .SeqNum(0)
665 .Time(0)
666 .Marker()
667 .Build())
668 .packets;
669
670 ASSERT_THAT(packets, SizeIs(1));
671 EXPECT_THAT(PacketPayload(packets[0]),
672 ElementsAreArray(FlatVector({StartCode(),
673 {kSps, 1, 2, 3},
674 StartCode(),
675 {kPps, 4, 5, 6},
676 StartCode(),
677 {kIdr, 7, 8, 9}})));
678}
679
680TEST(H264PacketBufferTest, SingleNaluFixedBitstream) {
681 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
682
683 RTC_UNUSED(packet_buffer.InsertPacket(
684 Packet(kH264SingleNalu).Sps({1, 2, 3}).SeqNum(0).Time(0).Build()));
685 RTC_UNUSED(packet_buffer.InsertPacket(
686 Packet(kH264SingleNalu).Pps({4, 5, 6}).SeqNum(1).Time(0).Build()));
687 auto packets = packet_buffer
688 .InsertPacket(Packet(kH264SingleNalu)
689 .Idr({7, 8, 9})
690 .SeqNum(2)
691 .Time(0)
692 .Marker()
693 .Build())
694 .packets;
695
696 ASSERT_THAT(packets, SizeIs(3));
697 EXPECT_THAT(PacketPayload(packets[0]),
698 ElementsAreArray(FlatVector({StartCode(), {kSps, 1, 2, 3}})));
699 EXPECT_THAT(PacketPayload(packets[1]),
700 ElementsAreArray(FlatVector({StartCode(), {kPps, 4, 5, 6}})));
701 EXPECT_THAT(PacketPayload(packets[2]),
702 ElementsAreArray(FlatVector({StartCode(), {kIdr, 7, 8, 9}})));
703}
704
705TEST(H264PacketBufferTest, StapaAndFuaFixedBitstream) {
706 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
707
708 RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264StapA)
709 .Sps({1, 2, 3})
710 .Pps({4, 5, 6})
711 .SeqNum(0)
712 .Time(0)
713 .Build()));
714 RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
715 .Idr({8, 8, 8})
716 .SeqNum(1)
717 .Time(0)
718 .AsFirstFragment()
719 .Build()));
720 auto packets = packet_buffer
721 .InsertPacket(Packet(kH264FuA)
722 .Idr({9, 9, 9})
723 .SeqNum(2)
724 .Time(0)
725 .Marker()
726 .Build())
727 .packets;
728
729 ASSERT_THAT(packets, SizeIs(3));
730 EXPECT_THAT(
731 PacketPayload(packets[0]),
732 ElementsAreArray(FlatVector(
733 {StartCode(), {kSps, 1, 2, 3}, StartCode(), {kPps, 4, 5, 6}})));
734 EXPECT_THAT(PacketPayload(packets[1]),
735 ElementsAreArray(FlatVector({StartCode(), {8, 8, 8}})));
736 // Third is a continuation of second, so only the payload is expected.
737 EXPECT_THAT(PacketPayload(packets[2]),
738 ElementsAreArray(FlatVector({{9, 9, 9}})));
739}
740
741TEST(H264PacketBufferTest, FullPacketBufferDoesNotBlockKeyframe) {
742 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
743
744 for (int i = 0; i < kBufferSize; ++i) {
745 EXPECT_THAT(
746 packet_buffer
747 .InsertPacket(
748 Packet(kH264SingleNalu).Slice().SeqNum(i).Time(0).Build())
749 .packets,
750 IsEmpty());
751 }
752
753 EXPECT_THAT(packet_buffer
754 .InsertPacket(Packet(kH264StapA)
755 .Sps()
756 .Pps()
757 .Idr()
758 .SeqNum(kBufferSize)
759 .Time(1)
760 .Marker()
761 .Build())
762 .packets,
763 SizeIs(1));
764}
765
766TEST(H264PacketBufferTest, TooManyNalusInPacket) {
767 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
768
769 std::unique_ptr<H264PacketBuffer::Packet> packet(
770 Packet(kH264StapA).Sps().Pps().Idr().SeqNum(1).Time(1).Marker().Build());
771 auto& h264_header =
772 absl::get<RTPVideoHeaderH264>(packet->video_header.video_type_header);
773 h264_header.nalus_length = kMaxNalusPerPacket + 1;
774
775 EXPECT_THAT(packet_buffer.InsertPacket(std::move(packet)).packets, IsEmpty());
776}
777
778} // namespace
779} // namespace webrtc