xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2012 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_vp8_test_helper.h"
12 
13 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
14 #include "test/gmock.h"
15 #include "test/gtest.h"
16 
17 // VP8 payload descriptor
18 // https://datatracker.ietf.org/doc/html/rfc7741#section-4.2
19 //
20 //       0 1 2 3 4 5 6 7
21 //      +-+-+-+-+-+-+-+-+
22 //      |X|R|N|S|R| PID | (REQUIRED)
23 //      +-+-+-+-+-+-+-+-+
24 // X:   |I|L|T|K| RSV   | (OPTIONAL)
25 //      +-+-+-+-+-+-+-+-+
26 // I:   |M| PictureID   | (OPTIONAL)
27 //      +-+-+-+-+-+-+-+-+
28 //      |   PictureID   |
29 //      +-+-+-+-+-+-+-+-+
30 // L:   |   TL0PICIDX   | (OPTIONAL)
31 //      +-+-+-+-+-+-+-+-+
32 // T/K: |TID|Y| KEYIDX  | (OPTIONAL)
33 //      +-+-+-+-+-+-+-+-+
34 
35 namespace webrtc {
36 namespace {
37 
38 using ::testing::ElementsAreArray;
39 
40 constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
41 
Bit(uint8_t byte,int position)42 int Bit(uint8_t byte, int position) {
43   return (byte >> position) & 0x01;
44 }
45 
46 }  // namespace
47 
RtpFormatVp8TestHelper(const RTPVideoHeaderVP8 * hdr,size_t payload_len)48 RtpFormatVp8TestHelper::RtpFormatVp8TestHelper(const RTPVideoHeaderVP8* hdr,
49                                                size_t payload_len)
50     : hdr_info_(hdr), payload_(payload_len) {
51   for (size_t i = 0; i < payload_.size(); ++i) {
52     payload_[i] = i;
53   }
54 }
55 
56 RtpFormatVp8TestHelper::~RtpFormatVp8TestHelper() = default;
57 
GetAllPacketsAndCheck(RtpPacketizerVp8 * packetizer,rtc::ArrayView<const size_t> expected_sizes)58 void RtpFormatVp8TestHelper::GetAllPacketsAndCheck(
59     RtpPacketizerVp8* packetizer,
60     rtc::ArrayView<const size_t> expected_sizes) {
61   EXPECT_EQ(packetizer->NumPackets(), expected_sizes.size());
62   const uint8_t* data_ptr = payload_.begin();
63   RtpPacketToSend packet(kNoExtensions);
64   for (size_t i = 0; i < expected_sizes.size(); ++i) {
65     EXPECT_TRUE(packetizer->NextPacket(&packet));
66     auto rtp_payload = packet.payload();
67     EXPECT_EQ(rtp_payload.size(), expected_sizes[i]);
68 
69     int payload_offset = CheckHeader(rtp_payload, /*first=*/i == 0);
70     // Verify that the payload (i.e., after the headers) of the packet is
71     // identical to the expected (as found in data_ptr).
72     auto vp8_payload = rtp_payload.subview(payload_offset);
73     ASSERT_GE(payload_.end() - data_ptr, static_cast<int>(vp8_payload.size()));
74     EXPECT_THAT(vp8_payload, ElementsAreArray(data_ptr, vp8_payload.size()));
75     data_ptr += vp8_payload.size();
76   }
77   EXPECT_EQ(payload_.end() - data_ptr, 0);
78 }
79 
CheckHeader(rtc::ArrayView<const uint8_t> buffer,bool first)80 int RtpFormatVp8TestHelper::CheckHeader(rtc::ArrayView<const uint8_t> buffer,
81                                         bool first) {
82   int x_bit = Bit(buffer[0], 7);
83   EXPECT_EQ(Bit(buffer[0], 6), 0);  // Reserved.
84   EXPECT_EQ(Bit(buffer[0], 5), hdr_info_->nonReference ? 1 : 0);
85   EXPECT_EQ(Bit(buffer[0], 4), first ? 1 : 0);
86   EXPECT_EQ(buffer[0] & 0x0f, 0);  // RtpPacketizerVp8 always uses partition 0.
87 
88   int payload_offset = 1;
89   if (hdr_info_->pictureId != kNoPictureId ||
90       hdr_info_->temporalIdx != kNoTemporalIdx ||
91       hdr_info_->tl0PicIdx != kNoTl0PicIdx || hdr_info_->keyIdx != kNoKeyIdx) {
92     EXPECT_EQ(x_bit, 1);
93     ++payload_offset;
94     CheckPictureID(buffer, &payload_offset);
95     CheckTl0PicIdx(buffer, &payload_offset);
96     CheckTIDAndKeyIdx(buffer, &payload_offset);
97     EXPECT_EQ(buffer[1] & 0x07, 0);  // Reserved.
98   } else {
99     EXPECT_EQ(x_bit, 0);
100   }
101 
102   return payload_offset;
103 }
104 
105 // Verify that the I bit and the PictureID field are both set in accordance
106 // with the information in hdr_info_->pictureId.
CheckPictureID(rtc::ArrayView<const uint8_t> buffer,int * offset)107 void RtpFormatVp8TestHelper::CheckPictureID(
108     rtc::ArrayView<const uint8_t> buffer,
109     int* offset) {
110   int i_bit = Bit(buffer[1], 7);
111   if (hdr_info_->pictureId != kNoPictureId) {
112     EXPECT_EQ(i_bit, 1);
113     int two_byte_picture_id = Bit(buffer[*offset], 7);
114     EXPECT_EQ(two_byte_picture_id, 1);
115     EXPECT_EQ(buffer[*offset] & 0x7F, (hdr_info_->pictureId >> 8) & 0x7F);
116     EXPECT_EQ(buffer[(*offset) + 1], hdr_info_->pictureId & 0xFF);
117     (*offset) += 2;
118   } else {
119     EXPECT_EQ(i_bit, 0);
120   }
121 }
122 
123 // Verify that the L bit and the TL0PICIDX field are both set in accordance
124 // with the information in hdr_info_->tl0PicIdx.
CheckTl0PicIdx(rtc::ArrayView<const uint8_t> buffer,int * offset)125 void RtpFormatVp8TestHelper::CheckTl0PicIdx(
126     rtc::ArrayView<const uint8_t> buffer,
127     int* offset) {
128   int l_bit = Bit(buffer[1], 6);
129   if (hdr_info_->tl0PicIdx != kNoTl0PicIdx) {
130     EXPECT_EQ(l_bit, 1);
131     EXPECT_EQ(buffer[*offset], hdr_info_->tl0PicIdx);
132     ++*offset;
133   } else {
134     EXPECT_EQ(l_bit, 0);
135   }
136 }
137 
138 // Verify that the T bit and the TL0PICIDX field, and the K bit and KEYIDX
139 // field are all set in accordance with the information in
140 // hdr_info_->temporalIdx and hdr_info_->keyIdx, respectively.
CheckTIDAndKeyIdx(rtc::ArrayView<const uint8_t> buffer,int * offset)141 void RtpFormatVp8TestHelper::CheckTIDAndKeyIdx(
142     rtc::ArrayView<const uint8_t> buffer,
143     int* offset) {
144   int t_bit = Bit(buffer[1], 5);
145   int k_bit = Bit(buffer[1], 4);
146   if (hdr_info_->temporalIdx == kNoTemporalIdx &&
147       hdr_info_->keyIdx == kNoKeyIdx) {
148     EXPECT_EQ(t_bit, 0);
149     EXPECT_EQ(k_bit, 0);
150     return;
151   }
152   int temporal_id = (buffer[*offset] & 0xC0) >> 6;
153   int y_bit = Bit(buffer[*offset], 5);
154   int key_idx = buffer[*offset] & 0x1f;
155   if (hdr_info_->temporalIdx != kNoTemporalIdx) {
156     EXPECT_EQ(t_bit, 1);
157     EXPECT_EQ(temporal_id, hdr_info_->temporalIdx);
158     EXPECT_EQ(y_bit, hdr_info_->layerSync ? 1 : 0);
159   } else {
160     EXPECT_EQ(t_bit, 0);
161     EXPECT_EQ(temporal_id, 0);
162     EXPECT_EQ(y_bit, 0);
163   }
164   if (hdr_info_->keyIdx != kNoKeyIdx) {
165     EXPECT_EQ(k_bit, 1);
166     EXPECT_EQ(key_idx, hdr_info_->keyIdx);
167   } else {
168     EXPECT_EQ(k_bit, 0);
169     EXPECT_EQ(key_idx, 0);
170   }
171   ++*offset;
172 }
173 
174 }  // namespace webrtc
175