blob: 4f2331da2896cfb0ca98c2d0058ab91b453abec0 [file] [log] [blame]
philipel10dc1a62021-09-15 08:45:431/*
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 {
philipel42754482021-09-24 10:26:53201 return rtc::CopyOnWriteBuffer(nalu_payloads_[0]);
philipel10dc1a62021-09-15 08:45:43202}
203
204rtc::CopyOnWriteBuffer Packet::BuildSingleNaluPayload() const {
205 rtc::CopyOnWriteBuffer res;
206 auto& h264_header = H264Header();
207 res.AppendData(&h264_header.nalus[0].type, 1);
philipel42754482021-09-24 10:26:53208 res.AppendData(nalu_payloads_[0]);
philipel10dc1a62021-09-15 08:45:43209 return res;
210}
211
212rtc::CopyOnWriteBuffer Packet::BuildStapAPayload() const {
213 rtc::CopyOnWriteBuffer res;
214
215 const uint8_t indicator = H264::NaluType::kStapA;
216 res.AppendData(&indicator, 1);
217
218 auto& h264_header = H264Header();
219 for (size_t i = 0; i < h264_header.nalus_length; ++i) {
220 // The two first bytes indicates the nalu segment size.
221 uint8_t length_as_array[2] = {
222 0, static_cast<uint8_t>(nalu_payloads_[i].size() + 1)};
223 res.AppendData(length_as_array);
224
225 res.AppendData(&h264_header.nalus[i].type, 1);
philipel42754482021-09-24 10:26:53226 res.AppendData(nalu_payloads_[i]);
philipel10dc1a62021-09-15 08:45:43227 }
228 return res;
229}
230
231rtc::ArrayView<const uint8_t> PacketPayload(
232 const std::unique_ptr<H264PacketBuffer::Packet>& packet) {
233 return packet->video_payload;
234}
235
236std::vector<uint8_t> FlatVector(
237 const std::vector<std::vector<uint8_t>>& elems) {
238 std::vector<uint8_t> res;
239 for (const auto& elem : elems) {
240 res.insert(res.end(), elem.begin(), elem.end());
241 }
242 return res;
243}
244
245TEST(H264PacketBufferTest, IdrIsKeyframe) {
246 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/true);
247
248 EXPECT_THAT(
249 packet_buffer.InsertPacket(Packet(kH264SingleNalu).Idr().Marker().Build())
250 .packets,
251 SizeIs(1));
252}
253
254TEST(H264PacketBufferTest, IdrIsNotKeyframe) {
255 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
256
257 EXPECT_THAT(
258 packet_buffer.InsertPacket(Packet(kH264SingleNalu).Idr().Marker().Build())
259 .packets,
260 IsEmpty());
261}
262
263TEST(H264PacketBufferTest, IdrIsKeyframeFuaRequiresFirstFragmet) {
264 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/true);
265
266 // Not marked as the first fragment
267 EXPECT_THAT(
268 packet_buffer
269 .InsertPacket(Packet(kH264FuA).Idr().SeqNum(0).Time(0).Build())
270 .packets,
271 IsEmpty());
272
273 EXPECT_THAT(packet_buffer
274 .InsertPacket(
275 Packet(kH264FuA).Idr().SeqNum(1).Time(0).Marker().Build())
276 .packets,
277 IsEmpty());
278
279 // Marked as first fragment
280 EXPECT_THAT(packet_buffer
281 .InsertPacket(Packet(kH264FuA)
282 .Idr()
283 .SeqNum(2)
284 .Time(1)
285 .AsFirstFragment()
286 .Build())
287 .packets,
288 IsEmpty());
289
290 EXPECT_THAT(packet_buffer
291 .InsertPacket(
292 Packet(kH264FuA).Idr().SeqNum(3).Time(1).Marker().Build())
293 .packets,
294 SizeIs(2));
295}
296
297TEST(H264PacketBufferTest, SpsPpsIdrIsKeyframeSingleNalus) {
298 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
299
300 RTC_UNUSED(packet_buffer.InsertPacket(
301 Packet(kH264SingleNalu).Sps().SeqNum(0).Time(0).Build()));
302 RTC_UNUSED(packet_buffer.InsertPacket(
303 Packet(kH264SingleNalu).Pps().SeqNum(1).Time(0).Build()));
304 EXPECT_THAT(
305 packet_buffer
306 .InsertPacket(
307 Packet(kH264SingleNalu).Idr().SeqNum(2).Time(0).Marker().Build())
308 .packets,
309 SizeIs(3));
310}
311
312TEST(H264PacketBufferTest, PpsIdrIsNotKeyframeSingleNalus) {
313 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
314
315 RTC_UNUSED(packet_buffer.InsertPacket(
316 Packet(kH264SingleNalu).Pps().SeqNum(0).Time(0).Build()));
317 EXPECT_THAT(
318 packet_buffer
319 .InsertPacket(
320 Packet(kH264SingleNalu).Idr().SeqNum(1).Time(0).Marker().Build())
321 .packets,
322 IsEmpty());
323}
324
325TEST(H264PacketBufferTest, SpsIdrIsNotKeyframeSingleNalus) {
326 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
327
328 RTC_UNUSED(packet_buffer.InsertPacket(
329 Packet(kH264SingleNalu).Sps().SeqNum(0).Time(0).Build()));
330 EXPECT_THAT(
331 packet_buffer
332 .InsertPacket(
333 Packet(kH264SingleNalu).Idr().SeqNum(1).Time(0).Marker().Build())
334 .packets,
335 IsEmpty());
336}
337
338TEST(H264PacketBufferTest, SpsPpsIdrIsKeyframeStapA) {
339 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
340
341 EXPECT_THAT(packet_buffer
342 .InsertPacket(Packet(kH264StapA)
343 .Sps()
344 .Pps()
345 .Idr()
346 .SeqNum(0)
347 .Time(0)
348 .Marker()
349 .Build())
350 .packets,
351 SizeIs(1));
352}
353
354TEST(H264PacketBufferTest, PpsIdrIsNotKeyframeStapA) {
355 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
356
357 EXPECT_THAT(
358 packet_buffer
359 .InsertPacket(
360 Packet(kH264StapA).Pps().Idr().SeqNum(0).Time(0).Marker().Build())
361 .packets,
362 IsEmpty());
363}
364
365TEST(H264PacketBufferTest, SpsIdrIsNotKeyframeStapA) {
366 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
367
368 EXPECT_THAT(
369 packet_buffer
370 .InsertPacket(
371 Packet(kH264StapA).Sps().Idr().SeqNum(2).Time(2).Marker().Build())
372 .packets,
373 IsEmpty());
374
375 EXPECT_THAT(packet_buffer
376 .InsertPacket(Packet(kH264StapA)
377 .Sps()
378 .Pps()
379 .Idr()
380 .SeqNum(3)
381 .Time(3)
382 .Marker()
383 .Build())
384 .packets,
385 SizeIs(1));
386}
387
388TEST(H264PacketBufferTest, InsertingSpsPpsLastCompletesKeyframe) {
389 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
390
391 RTC_UNUSED(packet_buffer.InsertPacket(
392 Packet(kH264SingleNalu).Idr().SeqNum(2).Time(1).Marker().Build()));
393
394 EXPECT_THAT(packet_buffer
395 .InsertPacket(
396 Packet(kH264StapA).Sps().Pps().SeqNum(1).Time(1).Build())
397 .packets,
398 SizeIs(2));
399}
400
401TEST(H264PacketBufferTest, InsertingMidFuaCompletesFrame) {
402 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
403
404 EXPECT_THAT(packet_buffer
405 .InsertPacket(Packet(kH264StapA)
406 .Sps()
407 .Pps()
408 .Idr()
409 .SeqNum(0)
410 .Time(0)
411 .Marker()
412 .Build())
413 .packets,
414 SizeIs(1));
415
416 RTC_UNUSED(packet_buffer.InsertPacket(
417 Packet(kH264FuA).Slice().SeqNum(1).Time(1).AsFirstFragment().Build()));
418 RTC_UNUSED(packet_buffer.InsertPacket(
419 Packet(kH264FuA).Slice().SeqNum(3).Time(1).Marker().Build()));
420 EXPECT_THAT(
421 packet_buffer
422 .InsertPacket(Packet(kH264FuA).Slice().SeqNum(2).Time(1).Build())
423 .packets,
424 SizeIs(3));
425}
426
427TEST(H264PacketBufferTest, SeqNumJumpDoesNotCompleteFrame) {
428 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
429
430 EXPECT_THAT(packet_buffer
431 .InsertPacket(Packet(kH264StapA)
432 .Sps()
433 .Pps()
434 .Idr()
435 .SeqNum(0)
436 .Time(0)
437 .Marker()
438 .Build())
439 .packets,
440 SizeIs(1));
441
442 EXPECT_THAT(
443 packet_buffer
444 .InsertPacket(Packet(kH264FuA).Slice().SeqNum(1).Time(1).Build())
445 .packets,
446 IsEmpty());
447
448 // Add `kBufferSize` to make the index of the sequence number wrap and end up
449 // where the packet with sequence number 2 would have ended up.
450 EXPECT_THAT(packet_buffer
451 .InsertPacket(Packet(kH264FuA)
452 .Slice()
453 .SeqNum(2 + kBufferSize)
454 .Time(3)
455 .Marker()
456 .Build())
457 .packets,
458 IsEmpty());
459}
460
461TEST(H264PacketBufferTest, OldFramesAreNotCompletedAfterBufferWrap) {
462 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
463
464 EXPECT_THAT(packet_buffer
465 .InsertPacket(Packet(kH264SingleNalu)
466 .Slice()
467 .SeqNum(1)
468 .Time(1)
469 .Marker()
470 .Build())
471 .packets,
472 IsEmpty());
473
474 // New keyframe, preceedes packet with sequence number 1 in the buffer.
475 EXPECT_THAT(packet_buffer
476 .InsertPacket(Packet(kH264StapA)
477 .Sps()
478 .Pps()
479 .Idr()
480 .SeqNum(kBufferSize)
481 .Time(kBufferSize)
482 .Marker()
483 .Build())
484 .packets,
485 SizeIs(1));
486}
487
488TEST(H264PacketBufferTest, OldPacketsDontBlockNewPackets) {
489 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
490 EXPECT_THAT(packet_buffer
491 .InsertPacket(Packet(kH264StapA)
492 .Sps()
493 .Pps()
494 .Idr()
495 .SeqNum(kBufferSize)
496 .Time(kBufferSize)
497 .Marker()
498 .Build())
499 .packets,
500 SizeIs(1));
501
502 RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
503 .Slice()
504 .SeqNum(kBufferSize + 1)
505 .Time(kBufferSize + 1)
506 .AsFirstFragment()
507 .Build()));
508
509 RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
510 .Slice()
511 .SeqNum(kBufferSize + 3)
512 .Time(kBufferSize + 1)
513 .Marker()
514 .Build()));
515 EXPECT_THAT(
516 packet_buffer
517 .InsertPacket(Packet(kH264FuA).Slice().SeqNum(2).Time(2).Build())
518 .packets,
519 IsEmpty());
520
521 EXPECT_THAT(packet_buffer
522 .InsertPacket(Packet(kH264FuA)
523 .Slice()
524 .SeqNum(kBufferSize + 2)
525 .Time(kBufferSize + 1)
526 .Build())
527 .packets,
528 SizeIs(3));
529}
530
531TEST(H264PacketBufferTest, OldPacketDoesntCompleteFrame) {
532 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
533
534 EXPECT_THAT(packet_buffer
535 .InsertPacket(Packet(kH264StapA)
536 .Sps()
537 .Pps()
538 .Idr()
539 .SeqNum(kBufferSize)
540 .Time(kBufferSize)
541 .Marker()
542 .Build())
543 .packets,
544 SizeIs(1));
545
546 EXPECT_THAT(packet_buffer
547 .InsertPacket(Packet(kH264FuA)
548 .Slice()
549 .SeqNum(kBufferSize + 3)
550 .Time(kBufferSize + 1)
551 .Marker()
552 .Build())
553 .packets,
554 IsEmpty());
555
556 EXPECT_THAT(
557 packet_buffer
558 .InsertPacket(
559 Packet(kH264FuA).Slice().SeqNum(2).Time(2).Marker().Build())
560 .packets,
561 IsEmpty());
562
563 EXPECT_THAT(packet_buffer
564 .InsertPacket(Packet(kH264FuA)
565 .Slice()
566 .SeqNum(kBufferSize + 1)
567 .Time(kBufferSize + 1)
568 .AsFirstFragment()
569 .Build())
570 .packets,
571 IsEmpty());
572}
573
574TEST(H264PacketBufferTest, FrameBoundariesAreSet) {
575 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
576
577 auto key = packet_buffer.InsertPacket(
578 Packet(kH264StapA).Sps().Pps().Idr().SeqNum(1).Time(1).Marker().Build());
579
580 ASSERT_THAT(key.packets, SizeIs(1));
581 EXPECT_TRUE(key.packets[0]->video_header.is_first_packet_in_frame);
582 EXPECT_TRUE(key.packets[0]->video_header.is_last_packet_in_frame);
583
584 RTC_UNUSED(packet_buffer.InsertPacket(
585 Packet(kH264FuA).Slice().SeqNum(2).Time(2).Build()));
586 RTC_UNUSED(packet_buffer.InsertPacket(
587 Packet(kH264FuA).Slice().SeqNum(3).Time(2).Build()));
588 auto delta = packet_buffer.InsertPacket(
589 Packet(kH264FuA).Slice().SeqNum(4).Time(2).Marker().Build());
590
591 ASSERT_THAT(delta.packets, SizeIs(3));
592 EXPECT_TRUE(delta.packets[0]->video_header.is_first_packet_in_frame);
593 EXPECT_FALSE(delta.packets[0]->video_header.is_last_packet_in_frame);
594
595 EXPECT_FALSE(delta.packets[1]->video_header.is_first_packet_in_frame);
596 EXPECT_FALSE(delta.packets[1]->video_header.is_last_packet_in_frame);
597
598 EXPECT_FALSE(delta.packets[2]->video_header.is_first_packet_in_frame);
599 EXPECT_TRUE(delta.packets[2]->video_header.is_last_packet_in_frame);
600}
601
602TEST(H264PacketBufferTest, ResolutionSetOnFirstPacket) {
603 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
604
605 RTC_UNUSED(packet_buffer.InsertPacket(
606 Packet(kH264SingleNalu).Aud().SeqNum(1).Time(1).Build()));
607 auto res = packet_buffer.InsertPacket(Packet(kH264StapA)
608 .SpsWithResolution({320, 240})
609 .Pps()
610 .Idr()
611 .SeqNum(2)
612 .Time(1)
613 .Marker()
614 .Build());
615
616 ASSERT_THAT(res.packets, SizeIs(2));
617 EXPECT_THAT(res.packets[0]->video_header.width, Eq(320));
618 EXPECT_THAT(res.packets[0]->video_header.height, Eq(240));
619}
620
621TEST(H264PacketBufferTest, KeyframeAndDeltaFrameSetOnFirstPacket) {
622 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
623
624 RTC_UNUSED(packet_buffer.InsertPacket(
625 Packet(kH264SingleNalu).Aud().SeqNum(1).Time(1).Build()));
626 auto key = packet_buffer.InsertPacket(
627 Packet(kH264StapA).Sps().Pps().Idr().SeqNum(2).Time(1).Marker().Build());
628
629 auto delta = packet_buffer.InsertPacket(
630 Packet(kH264SingleNalu).Slice().SeqNum(3).Time(2).Marker().Build());
631
632 ASSERT_THAT(key.packets, SizeIs(2));
633 EXPECT_THAT(key.packets[0]->video_header.frame_type,
634 Eq(VideoFrameType::kVideoFrameKey));
635 ASSERT_THAT(delta.packets, SizeIs(1));
636 EXPECT_THAT(delta.packets[0]->video_header.frame_type,
637 Eq(VideoFrameType::kVideoFrameDelta));
638}
639
640TEST(H264PacketBufferTest, RtpSeqNumWrap) {
641 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
642
643 RTC_UNUSED(packet_buffer.InsertPacket(
644 Packet(kH264StapA).Sps().Pps().SeqNum(0xffff).Time(0).Build()));
645
646 RTC_UNUSED(packet_buffer.InsertPacket(
647 Packet(kH264FuA).Idr().SeqNum(0).Time(0).Build()));
648 EXPECT_THAT(packet_buffer
649 .InsertPacket(
650 Packet(kH264FuA).Idr().SeqNum(1).Time(0).Marker().Build())
651 .packets,
652 SizeIs(3));
653}
654
655TEST(H264PacketBufferTest, StapAFixedBitstream) {
656 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
657
658 auto packets = packet_buffer
659 .InsertPacket(Packet(kH264StapA)
660 .Sps({1, 2, 3})
661 .Pps({4, 5, 6})
662 .Idr({7, 8, 9})
663 .SeqNum(0)
664 .Time(0)
665 .Marker()
666 .Build())
667 .packets;
668
669 ASSERT_THAT(packets, SizeIs(1));
670 EXPECT_THAT(PacketPayload(packets[0]),
671 ElementsAreArray(FlatVector({StartCode(),
672 {kSps, 1, 2, 3},
673 StartCode(),
674 {kPps, 4, 5, 6},
675 StartCode(),
676 {kIdr, 7, 8, 9}})));
677}
678
679TEST(H264PacketBufferTest, SingleNaluFixedBitstream) {
680 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
681
682 RTC_UNUSED(packet_buffer.InsertPacket(
683 Packet(kH264SingleNalu).Sps({1, 2, 3}).SeqNum(0).Time(0).Build()));
684 RTC_UNUSED(packet_buffer.InsertPacket(
685 Packet(kH264SingleNalu).Pps({4, 5, 6}).SeqNum(1).Time(0).Build()));
686 auto packets = packet_buffer
687 .InsertPacket(Packet(kH264SingleNalu)
688 .Idr({7, 8, 9})
689 .SeqNum(2)
690 .Time(0)
691 .Marker()
692 .Build())
693 .packets;
694
695 ASSERT_THAT(packets, SizeIs(3));
696 EXPECT_THAT(PacketPayload(packets[0]),
697 ElementsAreArray(FlatVector({StartCode(), {kSps, 1, 2, 3}})));
698 EXPECT_THAT(PacketPayload(packets[1]),
699 ElementsAreArray(FlatVector({StartCode(), {kPps, 4, 5, 6}})));
700 EXPECT_THAT(PacketPayload(packets[2]),
701 ElementsAreArray(FlatVector({StartCode(), {kIdr, 7, 8, 9}})));
702}
703
704TEST(H264PacketBufferTest, StapaAndFuaFixedBitstream) {
705 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
706
707 RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264StapA)
708 .Sps({1, 2, 3})
709 .Pps({4, 5, 6})
710 .SeqNum(0)
711 .Time(0)
712 .Build()));
713 RTC_UNUSED(packet_buffer.InsertPacket(Packet(kH264FuA)
714 .Idr({8, 8, 8})
715 .SeqNum(1)
716 .Time(0)
717 .AsFirstFragment()
718 .Build()));
719 auto packets = packet_buffer
720 .InsertPacket(Packet(kH264FuA)
721 .Idr({9, 9, 9})
722 .SeqNum(2)
723 .Time(0)
724 .Marker()
725 .Build())
726 .packets;
727
728 ASSERT_THAT(packets, SizeIs(3));
729 EXPECT_THAT(
730 PacketPayload(packets[0]),
731 ElementsAreArray(FlatVector(
732 {StartCode(), {kSps, 1, 2, 3}, StartCode(), {kPps, 4, 5, 6}})));
733 EXPECT_THAT(PacketPayload(packets[1]),
734 ElementsAreArray(FlatVector({StartCode(), {8, 8, 8}})));
735 // Third is a continuation of second, so only the payload is expected.
736 EXPECT_THAT(PacketPayload(packets[2]),
737 ElementsAreArray(FlatVector({{9, 9, 9}})));
738}
739
740TEST(H264PacketBufferTest, FullPacketBufferDoesNotBlockKeyframe) {
741 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
742
743 for (int i = 0; i < kBufferSize; ++i) {
744 EXPECT_THAT(
745 packet_buffer
746 .InsertPacket(
747 Packet(kH264SingleNalu).Slice().SeqNum(i).Time(0).Build())
748 .packets,
749 IsEmpty());
750 }
751
752 EXPECT_THAT(packet_buffer
753 .InsertPacket(Packet(kH264StapA)
754 .Sps()
755 .Pps()
756 .Idr()
757 .SeqNum(kBufferSize)
758 .Time(1)
759 .Marker()
760 .Build())
761 .packets,
762 SizeIs(1));
763}
764
765TEST(H264PacketBufferTest, TooManyNalusInPacket) {
766 H264PacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false);
767
768 std::unique_ptr<H264PacketBuffer::Packet> packet(
769 Packet(kH264StapA).Sps().Pps().Idr().SeqNum(1).Time(1).Marker().Build());
770 auto& h264_header =
771 absl::get<RTPVideoHeaderH264>(packet->video_header.video_type_header);
772 h264_header.nalus_length = kMaxNalusPerPacket + 1;
773
774 EXPECT_THAT(packet_buffer.InsertPacket(std::move(packet)).packets, IsEmpty());
775}
776
777} // namespace
778} // namespace webrtc