henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 1 | /* |
phoglund@webrtc.org | 78088c2 | 2012-02-07 14:56:45 | [diff] [blame] | 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 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 | |
Mirko Bonadei | 92ea95e | 2017-09-15 04:47:31 | [diff] [blame] | 11 | #include "modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h" |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 12 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 13 | #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" |
| 14 | #include "test/gmock.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 04:47:31 | [diff] [blame] | 15 | #include "test/gtest.h" |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 16 | |
Emil Lundmark | 575498f | 2021-08-27 15:01:56 | [diff] [blame] | 17 | // VP8 payload descriptor |
| 18 | // https://datatracker.ietf.org/doc/html/rfc7741#section-4.2 |
| 19 | // |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 20 | // 0 1 2 3 4 5 6 7 |
| 21 | // +-+-+-+-+-+-+-+-+ |
Emil Lundmark | 575498f | 2021-08-27 15:01:56 | [diff] [blame] | 22 | // |X|R|N|S|R| PID | (REQUIRED) |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 23 | // +-+-+-+-+-+-+-+-+ |
Emil Lundmark | 575498f | 2021-08-27 15:01:56 | [diff] [blame] | 24 | // X: |I|L|T|K| RSV | (OPTIONAL) |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 25 | // +-+-+-+-+-+-+-+-+ |
Emil Lundmark | 575498f | 2021-08-27 15:01:56 | [diff] [blame] | 26 | // I: |M| PictureID | (OPTIONAL) |
| 27 | // +-+-+-+-+-+-+-+-+ |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 28 | // | PictureID | |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 29 | // +-+-+-+-+-+-+-+-+ |
| 30 | // L: | TL0PICIDX | (OPTIONAL) |
| 31 | // +-+-+-+-+-+-+-+-+ |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 32 | // T/K: |TID|Y| KEYIDX | (OPTIONAL) |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 33 | // +-+-+-+-+-+-+-+-+ |
| 34 | |
Emil Lundmark | 575498f | 2021-08-27 15:01:56 | [diff] [blame] | 35 | namespace webrtc { |
| 36 | namespace { |
| 37 | |
| 38 | using ::testing::ElementsAreArray; |
| 39 | |
| 40 | constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr; |
| 41 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 42 | int Bit(uint8_t byte, int position) { |
| 43 | return (byte >> position) & 0x01; |
| 44 | } |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 45 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 46 | } // namespace |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 47 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 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 | } |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 55 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 56 | RtpFormatVp8TestHelper::~RtpFormatVp8TestHelper() = default; |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 57 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 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]); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 68 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 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 | } |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 79 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 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. |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 87 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 88 | int payload_offset = 1; |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 89 | if (hdr_info_->pictureId != kNoPictureId || |
| 90 | hdr_info_->temporalIdx != kNoTemporalIdx || |
Yves Gerey | 665174f | 2018-06-19 13:03:05 | [diff] [blame] | 91 | hdr_info_->tl0PicIdx != kNoTl0PicIdx || hdr_info_->keyIdx != kNoKeyIdx) { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 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. |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 98 | } else { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 99 | EXPECT_EQ(x_bit, 0); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 100 | } |
| 101 | |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 102 | return payload_offset; |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 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. |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 107 | void RtpFormatVp8TestHelper::CheckPictureID( |
| 108 | rtc::ArrayView<const uint8_t> buffer, |
| 109 | int* offset) { |
| 110 | int i_bit = Bit(buffer[1], 7); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 111 | if (hdr_info_->pictureId != kNoPictureId) { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 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; |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 118 | } else { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 119 | EXPECT_EQ(i_bit, 0); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 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. |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 125 | void RtpFormatVp8TestHelper::CheckTl0PicIdx( |
| 126 | rtc::ArrayView<const uint8_t> buffer, |
| 127 | int* offset) { |
| 128 | int l_bit = Bit(buffer[1], 6); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 129 | if (hdr_info_->tl0PicIdx != kNoTl0PicIdx) { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 130 | EXPECT_EQ(l_bit, 1); |
| 131 | EXPECT_EQ(buffer[*offset], hdr_info_->tl0PicIdx); |
| 132 | ++*offset; |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 133 | } else { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 134 | EXPECT_EQ(l_bit, 0); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 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. |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 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); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 146 | if (hdr_info_->temporalIdx == kNoTemporalIdx && |
| 147 | hdr_info_->keyIdx == kNoKeyIdx) { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 148 | EXPECT_EQ(t_bit, 0); |
| 149 | EXPECT_EQ(k_bit, 0); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 150 | return; |
| 151 | } |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 152 | int temporal_id = (buffer[*offset] & 0xC0) >> 6; |
| 153 | int y_bit = Bit(buffer[*offset], 5); |
| 154 | int key_idx = buffer[*offset] & 0x1f; |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 155 | if (hdr_info_->temporalIdx != kNoTemporalIdx) { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 156 | EXPECT_EQ(t_bit, 1); |
| 157 | EXPECT_EQ(temporal_id, hdr_info_->temporalIdx); |
| 158 | EXPECT_EQ(y_bit, hdr_info_->layerSync ? 1 : 0); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 159 | } else { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 160 | EXPECT_EQ(t_bit, 0); |
| 161 | EXPECT_EQ(temporal_id, 0); |
| 162 | EXPECT_EQ(y_bit, 0); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 163 | } |
| 164 | if (hdr_info_->keyIdx != kNoKeyIdx) { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 165 | EXPECT_EQ(k_bit, 1); |
| 166 | EXPECT_EQ(key_idx, hdr_info_->keyIdx); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 167 | } else { |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 168 | EXPECT_EQ(k_bit, 0); |
| 169 | EXPECT_EQ(key_idx, 0); |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 170 | } |
Danil Chapovalov | 8a3c166 | 2018-08-30 18:54:58 | [diff] [blame] | 171 | ++*offset; |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 172 | } |
| 173 | |
henrik.lundin@webrtc.org | 00e7307 | 2011-12-21 08:51:36 | [diff] [blame] | 174 | } // namespace webrtc |