blob: b0c00277e547a5ef11e37d7b406b9bf7fbbb824d [file] [log] [blame]
Stefan Holmerf7044682018-07-17 10:16:41 +02001/*
2 * Copyright (c) 2018 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 <memory>
philipelbf2b6202018-08-27 14:33:18 +020012#include <set>
Stefan Holmerf7044682018-07-17 10:16:41 +020013
Stefan Holmer9416ef82018-07-19 10:34:38 +020014#include "call/rtp_payload_params.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020015#include "modules/video_coding/include/video_codec_interface.h"
philipelbf2b6202018-08-27 14:33:18 +020016#include "test/field_trial.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020017#include "test/gtest.h"
18
19namespace webrtc {
20namespace {
21const uint32_t kSsrc1 = 12345;
22const uint32_t kSsrc2 = 23456;
23const int16_t kPictureId = 123;
24const int16_t kTl0PicIdx = 20;
25const uint8_t kTemporalIdx = 1;
26const int16_t kInitialPictureId1 = 222;
27const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020028const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020029} // namespace
30
31TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
32 RtpPayloadState state2;
33 state2.picture_id = kPictureId;
34 state2.tl0_pic_idx = kTl0PicIdx;
35 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
36
37 RtpPayloadParams params(kSsrc2, &state2);
38 EncodedImage encoded_image;
39 encoded_image.rotation_ = kVideoRotation_90;
40 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020041 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020042
43 CodecSpecificInfo codec_info;
44 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
45 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020046 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020047 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020048 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020049 codec_info.codecSpecific.VP8.nonReference = true;
50
philipelbf2b6202018-08-27 14:33:18 +020051 RTPVideoHeader header =
52 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
53
54 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020055 codec_info.codecSpecific.VP8.temporalIdx = 1;
56 codec_info.codecSpecific.VP8.layerSync = true;
57
58 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020059
60 EXPECT_EQ(kVideoRotation_90, header.rotation);
61 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
62 EXPECT_EQ(1, header.simulcastIdx);
63 EXPECT_EQ(kVideoCodecVP8, header.codec);
philipelbf2b6202018-08-27 14:33:18 +020064 EXPECT_EQ(kPictureId + 2, header.vp8().pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +020065 EXPECT_EQ(kTemporalIdx, header.vp8().temporalIdx);
philipelbf2b6202018-08-27 14:33:18 +020066 EXPECT_EQ(kTl0PicIdx + 1, header.vp8().tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +020067 EXPECT_EQ(kNoKeyIdx, header.vp8().keyIdx);
68 EXPECT_TRUE(header.vp8().layerSync);
69 EXPECT_TRUE(header.vp8().nonReference);
70}
71
72TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
73 RtpPayloadState state;
74 state.picture_id = kPictureId;
75 state.tl0_pic_idx = kTl0PicIdx;
76 RtpPayloadParams params(kSsrc1, &state);
77
78 EncodedImage encoded_image;
79 encoded_image.rotation_ = kVideoRotation_90;
80 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020081 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +020082 CodecSpecificInfo codec_info;
83 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
84 codec_info.codecType = kVideoCodecVP9;
85 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
86 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +020087 codec_info.codecSpecific.VP9.temporal_idx = 2;
88 codec_info.codecSpecific.VP9.end_of_picture = false;
89
philipelbf2b6202018-08-27 14:33:18 +020090 RTPVideoHeader header =
91 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +020092
93 EXPECT_EQ(kVideoRotation_90, header.rotation);
94 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
95 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +020096 const auto& vp9_header =
97 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
98 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
99 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
100 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200101 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200102 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200103 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200104 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200105 codec_info.codecSpecific.VP9.end_of_picture);
106
107 // Next spatial layer.
108 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200109 codec_info.codecSpecific.VP9.end_of_picture = true;
110
Niels Möllerd3b8c632018-08-27 15:33:42 +0200111 encoded_image.SetSpatialIndex(1);
philipelbf2b6202018-08-27 14:33:18 +0200112 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200113
114 EXPECT_EQ(kVideoRotation_90, header.rotation);
115 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
116 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200117 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
118 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
119 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200120 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200121 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200122 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200123 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200124 codec_info.codecSpecific.VP9.end_of_picture);
125}
126
127TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_H264) {
128 RtpPayloadParams params(kSsrc1, {});
129
130 EncodedImage encoded_image;
131 CodecSpecificInfo codec_info;
132 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
133 codec_info.codecType = kVideoCodecH264;
134 codec_info.codecSpecific.H264.packetization_mode =
135 H264PacketizationMode::SingleNalUnit;
136
philipelbf2b6202018-08-27 14:33:18 +0200137 RTPVideoHeader header =
138 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200139
140 EXPECT_EQ(0, header.simulcastIdx);
141 EXPECT_EQ(kVideoCodecH264, header.codec);
142 const auto& h264 = absl::get<RTPVideoHeaderH264>(header.video_type_header);
143 EXPECT_EQ(H264PacketizationMode::SingleNalUnit, h264.packetization_mode);
144}
145
146TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
147 RtpPayloadState state;
148 state.picture_id = kInitialPictureId1;
149 state.tl0_pic_idx = kInitialTl0PicIdx1;
150
151 EncodedImage encoded_image;
152 CodecSpecificInfo codec_info;
153 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
154 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200155
156 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200157 RTPVideoHeader header =
158 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200159 EXPECT_EQ(kVideoCodecVP8, header.codec);
160 EXPECT_EQ(kInitialPictureId1 + 1, header.vp8().pictureId);
161
162 // State should hold latest used picture id and tl0_pic_idx.
163 state = params.state();
164 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
165 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
166}
167
168TEST(RtpPayloadParamsTest, PictureIdWraps) {
169 RtpPayloadState state;
170 state.picture_id = kMaxTwoBytePictureId;
171 state.tl0_pic_idx = kInitialTl0PicIdx1;
172
173 EncodedImage encoded_image;
174 CodecSpecificInfo codec_info;
175 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
176 codec_info.codecType = kVideoCodecVP8;
177 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
178
179 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200180 RTPVideoHeader header =
181 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200182 EXPECT_EQ(kVideoCodecVP8, header.codec);
183 EXPECT_EQ(0, header.vp8().pictureId);
184
185 // State should hold latest used picture id and tl0_pic_idx.
186 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
187 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
188}
189
190TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
191 RtpPayloadState state;
192 state.picture_id = kInitialPictureId1;
193 state.tl0_pic_idx = kInitialTl0PicIdx1;
194
195 EncodedImage encoded_image;
196 // Modules are sending for this test.
197 // OnEncodedImage, temporalIdx: 1.
198 CodecSpecificInfo codec_info;
199 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
200 codec_info.codecType = kVideoCodecVP8;
201 codec_info.codecSpecific.VP8.temporalIdx = 1;
202
203 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200204 RTPVideoHeader header =
205 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200206
207 EXPECT_EQ(kVideoCodecVP8, header.codec);
208 EXPECT_EQ(kInitialPictureId1 + 1, header.vp8().pictureId);
209 EXPECT_EQ(kInitialTl0PicIdx1, header.vp8().tl0PicIdx);
210
211 // OnEncodedImage, temporalIdx: 0.
212 codec_info.codecSpecific.VP8.temporalIdx = 0;
213
philipelbf2b6202018-08-27 14:33:18 +0200214 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200215 EXPECT_EQ(kVideoCodecVP8, header.codec);
216 EXPECT_EQ(kInitialPictureId1 + 2, header.vp8().pictureId);
217 EXPECT_EQ(kInitialTl0PicIdx1 + 1, header.vp8().tl0PicIdx);
218
219 // State should hold latest used picture id and tl0_pic_idx.
220 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
221 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
222}
223
224TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
225 RtpPayloadState state;
226 state.picture_id = kInitialPictureId1;
227 state.tl0_pic_idx = kInitialTl0PicIdx1;
228
229 EncodedImage encoded_image;
230 // Modules are sending for this test.
231 // OnEncodedImage, temporalIdx: 1.
232 CodecSpecificInfo codec_info;
233 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
234 codec_info.codecType = kVideoCodecVP9;
235 codec_info.codecSpecific.VP9.temporal_idx = 1;
236 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
237
238 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200239 RTPVideoHeader header =
240 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200241
242 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200243 const auto& vp9_header =
244 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
245 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
246 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200247
248 // OnEncodedImage, temporalIdx: 0.
249 codec_info.codecSpecific.VP9.temporal_idx = 0;
250
philipelbf2b6202018-08-27 14:33:18 +0200251 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200252
253 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200254 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
255 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200256
257 // OnEncodedImage, first_frame_in_picture = false
258 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
259
philipelbf2b6202018-08-27 14:33:18 +0200260 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200261
262 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200263 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
264 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200265
266 // State should hold latest used picture id and tl0_pic_idx.
267 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
268 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
269}
philipelbf2b6202018-08-27 14:33:18 +0200270
271TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
272 test::ScopedFieldTrials generic_picture_id(
273 "WebRTC-GenericPictureId/Enabled/");
274 RtpPayloadState state{};
275
276 EncodedImage encoded_image;
277 CodecSpecificInfo codec_info{};
278 codec_info.codecType = kVideoCodecGeneric;
279
280 RtpPayloadParams params(kSsrc1, &state);
281 RTPVideoHeader header =
282 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
283
284 EXPECT_EQ(kVideoCodecGeneric, header.codec);
285 ASSERT_TRUE(header.generic);
286 EXPECT_EQ(0, header.generic->frame_id);
287
288 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
289 ASSERT_TRUE(header.generic);
290 EXPECT_EQ(1, header.generic->frame_id);
291}
292
293class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
294 public:
295 enum LayerSync { kNoSync, kSync };
296
297 RtpPayloadParamsVp8ToGenericTest() : state_(), params_(123, &state_) {}
298
299 void ConvertAndCheck(int temporal_index,
300 int64_t shared_frame_id,
301 FrameType frame_type,
302 LayerSync layer_sync,
303 const std::set<int64_t>& expected_deps) {
304 EncodedImage encoded_image;
305 encoded_image._frameType = frame_type;
306
307 CodecSpecificInfo codec_info{};
308 codec_info.codecType = kVideoCodecVP8;
309 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
310 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
311
312 RTPVideoHeader header =
313 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
314
315 ASSERT_TRUE(header.generic);
316 EXPECT_TRUE(header.generic->higher_spatial_layers.empty());
317 EXPECT_EQ(header.generic->spatial_index, 0);
318
319 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
320 EXPECT_EQ(header.generic->temporal_index, temporal_index);
321 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
322 header.generic->dependencies.end());
323 EXPECT_EQ(expected_deps, actual_deps);
324 }
325
326 protected:
327 RtpPayloadState state_;
328 RtpPayloadParams params_;
329};
330
331TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
332 ConvertAndCheck(0, 0, kVideoFrameKey, kNoSync, {});
333 ConvertAndCheck(0, 1, kVideoFrameDelta, kNoSync, {0});
334 ConvertAndCheck(0, 2, kVideoFrameKey, kNoSync, {});
335}
336
337TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
338 ConvertAndCheck(0, 0, kVideoFrameKey, kNoSync, {});
339
340 EncodedImage encoded_image;
341 encoded_image._frameType = kVideoFrameDelta;
342 CodecSpecificInfo codec_info{};
343 codec_info.codecType = kVideoCodecVP8;
344 codec_info.codecSpecific.VP8.temporalIdx =
345 RtpGenericFrameDescriptor::kMaxTemporalLayers;
346 codec_info.codecSpecific.VP8.layerSync = false;
347
348 RTPVideoHeader header =
349 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
350 EXPECT_FALSE(header.generic);
351}
352
353TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
354 // 02120212 pattern
355 ConvertAndCheck(0, 0, kVideoFrameKey, kNoSync, {});
356 ConvertAndCheck(2, 1, kVideoFrameDelta, kNoSync, {0});
357 ConvertAndCheck(1, 2, kVideoFrameDelta, kNoSync, {0});
358 ConvertAndCheck(2, 3, kVideoFrameDelta, kNoSync, {0, 1, 2});
359
360 ConvertAndCheck(0, 4, kVideoFrameDelta, kNoSync, {0});
361 ConvertAndCheck(2, 5, kVideoFrameDelta, kNoSync, {2, 3, 4});
362 ConvertAndCheck(1, 6, kVideoFrameDelta, kSync, {4}); // layer sync
363 ConvertAndCheck(2, 7, kVideoFrameDelta, kNoSync, {4, 5, 6});
364}
365
366TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
367 // 0101 pattern
368 ConvertAndCheck(0, 0, kVideoFrameKey, kNoSync, {});
369 ConvertAndCheck(1, 1, kVideoFrameDelta, kNoSync, {0});
370
371 ConvertAndCheck(0, 5, kVideoFrameDelta, kNoSync, {0});
372 ConvertAndCheck(1, 10, kVideoFrameDelta, kNoSync, {1, 5});
373
374 ConvertAndCheck(0, 15, kVideoFrameDelta, kNoSync, {5});
375 ConvertAndCheck(1, 20, kVideoFrameDelta, kNoSync, {10, 15});
376}
377
Stefan Holmerf7044682018-07-17 10:16:41 +0200378} // namespace webrtc