1 /*
2 * Copyright (c) 2017 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/rtp_format_video_generic.h"
12
13 #include <algorithm>
14 #include <limits>
15 #include <memory>
16 #include <vector>
17
18 #include "api/array_view.h"
19 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
20 #include "modules/rtp_rtcp/source/byte_io.h"
21 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
22 #include "test/gmock.h"
23 #include "test/gtest.h"
24
25 namespace webrtc {
26 namespace {
27
28 using ::testing::Contains;
29 using ::testing::Each;
30 using ::testing::ElementsAreArray;
31 using ::testing::Le;
32
33 constexpr RtpPacketizer::PayloadSizeLimits kNoSizeLimits;
34
NextPacketFillPayloadSizes(RtpPacketizerGeneric * packetizer)35 std::vector<int> NextPacketFillPayloadSizes(RtpPacketizerGeneric* packetizer) {
36 RtpPacketToSend packet(nullptr);
37 std::vector<int> result;
38 while (packetizer->NextPacket(&packet)) {
39 result.push_back(packet.payload_size());
40 }
41 return result;
42 }
43
TEST(RtpPacketizerVideoGeneric,RespectsMaxPayloadSize)44 TEST(RtpPacketizerVideoGeneric, RespectsMaxPayloadSize) {
45 const size_t kPayloadSize = 50;
46 const uint8_t kPayload[kPayloadSize] = {};
47
48 RtpPacketizer::PayloadSizeLimits limits;
49 limits.max_payload_len = 6;
50 RtpPacketizerGeneric packetizer(kPayload, limits, RTPVideoHeader());
51
52 std::vector<int> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
53
54 EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
55 }
56
TEST(RtpPacketizerVideoGeneric,UsesMaxPayloadSize)57 TEST(RtpPacketizerVideoGeneric, UsesMaxPayloadSize) {
58 const size_t kPayloadSize = 50;
59 const uint8_t kPayload[kPayloadSize] = {};
60
61 RtpPacketizer::PayloadSizeLimits limits;
62 limits.max_payload_len = 6;
63 RtpPacketizerGeneric packetizer(kPayload, limits, RTPVideoHeader());
64
65 std::vector<int> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
66
67 // With kPayloadSize > max_payload_len^2, there should be packets that use
68 // all the payload, otherwise it is possible to use less packets.
69 EXPECT_THAT(payload_sizes, Contains(limits.max_payload_len));
70 }
71
TEST(RtpPacketizerVideoGeneric,WritesExtendedHeaderWhenPictureIdIsSet)72 TEST(RtpPacketizerVideoGeneric, WritesExtendedHeaderWhenPictureIdIsSet) {
73 const size_t kPayloadSize = 13;
74 const uint8_t kPayload[kPayloadSize] = {};
75
76 RTPVideoHeader rtp_video_header;
77 rtp_video_header.video_type_header.emplace<RTPVideoHeaderLegacyGeneric>()
78 .picture_id = 37;
79 rtp_video_header.frame_type = VideoFrameType::kVideoFrameKey;
80 RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, rtp_video_header);
81
82 RtpPacketToSend packet(nullptr);
83 ASSERT_TRUE(packetizer.NextPacket(&packet));
84
85 rtc::ArrayView<const uint8_t> payload = packet.payload();
86 EXPECT_EQ(payload.size(), 3 + kPayloadSize);
87 EXPECT_TRUE(payload[0] & 0x04); // Extended header bit is set.
88 // Frame id is 37.
89 EXPECT_EQ(0u, payload[1]);
90 EXPECT_EQ(37u, payload[2]);
91 }
92
TEST(RtpPacketizerVideoGeneric,RespectsMaxPayloadSizeWithExtendedHeader)93 TEST(RtpPacketizerVideoGeneric, RespectsMaxPayloadSizeWithExtendedHeader) {
94 const int kPayloadSize = 50;
95 const uint8_t kPayload[kPayloadSize] = {};
96
97 RtpPacketizer::PayloadSizeLimits limits;
98 limits.max_payload_len = 6;
99 RTPVideoHeader rtp_video_header;
100 rtp_video_header.video_type_header.emplace<RTPVideoHeaderLegacyGeneric>()
101 .picture_id = 37;
102 RtpPacketizerGeneric packetizer(kPayload, limits, rtp_video_header);
103
104 std::vector<int> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
105
106 EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
107 }
108
TEST(RtpPacketizerVideoGeneric,UsesMaxPayloadSizeWithExtendedHeader)109 TEST(RtpPacketizerVideoGeneric, UsesMaxPayloadSizeWithExtendedHeader) {
110 const int kPayloadSize = 50;
111 const uint8_t kPayload[kPayloadSize] = {};
112
113 RtpPacketizer::PayloadSizeLimits limits;
114 limits.max_payload_len = 6;
115 RTPVideoHeader rtp_video_header;
116 rtp_video_header.video_type_header.emplace<RTPVideoHeaderLegacyGeneric>()
117 .picture_id = 37;
118 RtpPacketizerGeneric packetizer(kPayload, limits, rtp_video_header);
119 std::vector<int> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
120
121 // With kPayloadSize > max_payload_len^2, there should be packets that use
122 // all the payload, otherwise it is possible to use less packets.
123 EXPECT_THAT(payload_sizes, Contains(limits.max_payload_len));
124 }
125
TEST(RtpPacketizerVideoGeneric,FrameIdOver15bitsWrapsAround)126 TEST(RtpPacketizerVideoGeneric, FrameIdOver15bitsWrapsAround) {
127 const int kPayloadSize = 13;
128 const uint8_t kPayload[kPayloadSize] = {};
129
130 RTPVideoHeader rtp_video_header;
131 rtp_video_header.video_type_header.emplace<RTPVideoHeaderLegacyGeneric>()
132 .picture_id = 0x8137;
133 rtp_video_header.frame_type = VideoFrameType::kVideoFrameKey;
134 RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, rtp_video_header);
135
136 RtpPacketToSend packet(nullptr);
137 ASSERT_TRUE(packetizer.NextPacket(&packet));
138
139 rtc::ArrayView<const uint8_t> payload = packet.payload();
140 EXPECT_TRUE(payload[0] & 0x04); // Extended header bit is set.
141 // Frame id is 0x137.
142 EXPECT_EQ(0x01u, payload[1]);
143 EXPECT_EQ(0x37u, payload[2]);
144 }
145
TEST(RtpPacketizerVideoGeneric,NoFrameIdDoesNotWriteExtendedHeader)146 TEST(RtpPacketizerVideoGeneric, NoFrameIdDoesNotWriteExtendedHeader) {
147 const int kPayloadSize = 13;
148 const uint8_t kPayload[kPayloadSize] = {};
149
150 RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, RTPVideoHeader());
151
152 RtpPacketToSend packet(nullptr);
153 ASSERT_TRUE(packetizer.NextPacket(&packet));
154
155 rtc::ArrayView<const uint8_t> payload = packet.payload();
156 EXPECT_FALSE(payload[0] & 0x04);
157 }
158
TEST(RtpPacketizerVideoGeneric,DoesNotWriteHeaderForRawPayload)159 TEST(RtpPacketizerVideoGeneric, DoesNotWriteHeaderForRawPayload) {
160 const uint8_t kPayload[] = {0x05, 0x25, 0x52};
161
162 RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits);
163
164 RtpPacketToSend packet(nullptr);
165 ASSERT_TRUE(packetizer.NextPacket(&packet));
166
167 rtc::ArrayView<const uint8_t> payload = packet.payload();
168 EXPECT_THAT(payload, ElementsAreArray(kPayload));
169 }
170
171 } // namespace
172 } // namespace webrtc
173