blob: 56ed2cdea62aea2aaa98a72a37608d633fe0dd01 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "call/rtp_payload_params.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <map>
philipelbf2b6202018-08-27 14:33:18 +020016#include <set>
Stefan Holmerf7044682018-07-17 10:16:41 +020017
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "absl/container/inlined_vector.h"
19#include "absl/types/optional.h"
20#include "absl/types/variant.h"
Erik Språngcbc0cba2020-04-18 14:36:59 +020021#include "api/transport/field_trial_based_config.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "api/video/video_content_type.h"
23#include "api/video/video_rotation.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "modules/video_coding/codecs/h264/include/h264_globals.h"
25#include "modules/video_coding/codecs/interface/common_constants.h"
26#include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
27#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020028#include "modules/video_coding/include/video_codec_interface.h"
philipelbf2b6202018-08-27 14:33:18 +020029#include "test/field_trial.h"
philipel8aba8fe2019-06-13 15:13:16 +020030#include "test/gmock.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020031#include "test/gtest.h"
32
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010033using ::testing::ElementsAre;
34using ::testing::IsEmpty;
Danil Chapovalov4b860c12020-05-19 14:48:19 +020035using ::testing::SizeIs;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010036
Qingsi Wang1c1b99e2020-01-07 19:16:33 +000037namespace webrtc {
38namespace {
Stefan Holmerf7044682018-07-17 10:16:41 +020039const uint32_t kSsrc1 = 12345;
40const uint32_t kSsrc2 = 23456;
41const int16_t kPictureId = 123;
42const int16_t kTl0PicIdx = 20;
43const uint8_t kTemporalIdx = 1;
44const int16_t kInitialPictureId1 = 222;
45const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020046const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020047} // namespace
48
49TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
50 RtpPayloadState state2;
51 state2.picture_id = kPictureId;
52 state2.tl0_pic_idx = kTl0PicIdx;
53 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
54
Erik Språngcbc0cba2020-04-18 14:36:59 +020055 RtpPayloadParams params(kSsrc2, &state2, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020056 EncodedImage encoded_image;
57 encoded_image.rotation_ = kVideoRotation_90;
58 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020059 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020060
61 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020062 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020063 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020064 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020065 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020066 codec_info.codecSpecific.VP8.nonReference = true;
67
philipelbf2b6202018-08-27 14:33:18 +020068 RTPVideoHeader header =
69 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
70
71 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020072 codec_info.codecSpecific.VP8.temporalIdx = 1;
73 codec_info.codecSpecific.VP8.layerSync = true;
74
75 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020076
77 EXPECT_EQ(kVideoRotation_90, header.rotation);
78 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
79 EXPECT_EQ(1, header.simulcastIdx);
80 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +000081 const auto& vp8_header =
82 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
83 EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
84 EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
85 EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
86 EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
87 EXPECT_TRUE(vp8_header.layerSync);
88 EXPECT_TRUE(vp8_header.nonReference);
Stefan Holmerf7044682018-07-17 10:16:41 +020089}
90
91TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
92 RtpPayloadState state;
93 state.picture_id = kPictureId;
94 state.tl0_pic_idx = kTl0PicIdx;
Erik Språngcbc0cba2020-04-18 14:36:59 +020095 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020096
97 EncodedImage encoded_image;
98 encoded_image.rotation_ = kVideoRotation_90;
99 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200100 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +0200101 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200102 codec_info.codecType = kVideoCodecVP9;
103 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
104 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200105 codec_info.codecSpecific.VP9.temporal_idx = 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100106 codec_info.end_of_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200107
philipelbf2b6202018-08-27 14:33:18 +0200108 RTPVideoHeader header =
109 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200110
111 EXPECT_EQ(kVideoRotation_90, header.rotation);
112 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
113 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100114 EXPECT_FALSE(header.color_space);
philipel29d88462018-08-08 14:26:00 +0200115 const auto& vp9_header =
116 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
117 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);
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100123 EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
Stefan Holmerf7044682018-07-17 10:16:41 +0200124
125 // Next spatial layer.
126 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100127 codec_info.end_of_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200128
Niels Möllerd3b8c632018-08-27 15:33:42 +0200129 encoded_image.SetSpatialIndex(1);
Johannes Krond0b69a82018-12-03 14:18:53 +0100130 ColorSpace color_space(
131 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
132 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
Danil Chapovalovb7698942019-02-05 11:32:19 +0100133 encoded_image.SetColorSpace(color_space);
philipelbf2b6202018-08-27 14:33:18 +0200134 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200135
136 EXPECT_EQ(kVideoRotation_90, header.rotation);
137 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
138 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100139 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
philipel29d88462018-08-08 14:26:00 +0200140 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
141 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
142 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200143 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200144 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200145 codec_info.codecSpecific.VP9.num_spatial_layers);
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100146 EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
Stefan Holmerf7044682018-07-17 10:16:41 +0200147}
148
Stefan Holmerf7044682018-07-17 10:16:41 +0200149TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
150 RtpPayloadState state;
151 state.picture_id = kInitialPictureId1;
152 state.tl0_pic_idx = kInitialTl0PicIdx1;
153
154 EncodedImage encoded_image;
155 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200156 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200157
Erik Språngcbc0cba2020-04-18 14:36:59 +0200158 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200159 RTPVideoHeader header =
160 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200161 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000162 EXPECT_EQ(kInitialPictureId1 + 1,
163 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200164
165 // State should hold latest used picture id and tl0_pic_idx.
166 state = params.state();
167 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
168 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
169}
170
171TEST(RtpPayloadParamsTest, PictureIdWraps) {
172 RtpPayloadState state;
173 state.picture_id = kMaxTwoBytePictureId;
174 state.tl0_pic_idx = kInitialTl0PicIdx1;
175
176 EncodedImage encoded_image;
177 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200178 codec_info.codecType = kVideoCodecVP8;
179 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
180
Erik Språngcbc0cba2020-04-18 14:36:59 +0200181 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200182 RTPVideoHeader header =
183 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200184 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000185 EXPECT_EQ(0,
186 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200187
188 // State should hold latest used picture id and tl0_pic_idx.
189 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
190 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
191}
192
193TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
194 RtpPayloadState state;
195 state.picture_id = kInitialPictureId1;
196 state.tl0_pic_idx = kInitialTl0PicIdx1;
197
198 EncodedImage encoded_image;
199 // Modules are sending for this test.
200 // OnEncodedImage, temporalIdx: 1.
201 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200202 codec_info.codecType = kVideoCodecVP8;
203 codec_info.codecSpecific.VP8.temporalIdx = 1;
204
Erik Språngcbc0cba2020-04-18 14:36:59 +0200205 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200206 RTPVideoHeader header =
207 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200208
209 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000210 const auto& vp8_header =
211 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
212 EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
213 EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200214
215 // OnEncodedImage, temporalIdx: 0.
216 codec_info.codecSpecific.VP8.temporalIdx = 0;
217
philipelbf2b6202018-08-27 14:33:18 +0200218 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200219 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000220 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
221 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200222
223 // State should hold latest used picture id and tl0_pic_idx.
224 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
225 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
226}
227
228TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
229 RtpPayloadState state;
230 state.picture_id = kInitialPictureId1;
231 state.tl0_pic_idx = kInitialTl0PicIdx1;
232
233 EncodedImage encoded_image;
234 // Modules are sending for this test.
235 // OnEncodedImage, temporalIdx: 1.
236 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200237 codec_info.codecType = kVideoCodecVP9;
238 codec_info.codecSpecific.VP9.temporal_idx = 1;
239 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
240
Erik Språngcbc0cba2020-04-18 14:36:59 +0200241 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200242 RTPVideoHeader header =
243 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200244
245 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200246 const auto& vp9_header =
247 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
248 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
249 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200250
251 // OnEncodedImage, temporalIdx: 0.
252 codec_info.codecSpecific.VP9.temporal_idx = 0;
253
philipelbf2b6202018-08-27 14:33:18 +0200254 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200255
256 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200257 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
258 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200259
260 // OnEncodedImage, first_frame_in_picture = false
261 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
262
philipelbf2b6202018-08-27 14:33:18 +0200263 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200264
265 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200266 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
267 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200268
269 // State should hold latest used picture id and tl0_pic_idx.
270 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
271 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
272}
philipelbf2b6202018-08-27 14:33:18 +0200273
274TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
275 test::ScopedFieldTrials generic_picture_id(
276 "WebRTC-GenericPictureId/Enabled/");
277 RtpPayloadState state{};
278
279 EncodedImage encoded_image;
philipeld1d03592019-03-01 13:53:55 +0100280 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200281 codec_info.codecType = kVideoCodecGeneric;
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100282 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
philipelbf2b6202018-08-27 14:33:18 +0200283
Erik Språngcbc0cba2020-04-18 14:36:59 +0200284 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200285 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100286 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
philipelbf2b6202018-08-27 14:33:18 +0200287
288 EXPECT_EQ(kVideoCodecGeneric, header.codec);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100289 const auto* generic =
290 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
291 ASSERT_TRUE(generic);
292 EXPECT_EQ(0, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200293
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100294 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
295 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100296 generic =
297 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
298 ASSERT_TRUE(generic);
299 EXPECT_EQ(1, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200300}
301
philipel8aba8fe2019-06-13 15:13:16 +0200302TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
philipel8aba8fe2019-06-13 15:13:16 +0200303 RtpPayloadState state{};
304
305 EncodedImage encoded_image;
306 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
307 CodecSpecificInfo codec_info;
308 codec_info.codecType = kVideoCodecGeneric;
309
Erik Språngcbc0cba2020-04-18 14:36:59 +0200310 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipel8aba8fe2019-06-13 15:13:16 +0200311 RTPVideoHeader header =
312 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
313
314 EXPECT_EQ(kVideoCodecGeneric, header.codec);
315 ASSERT_TRUE(header.generic);
316 EXPECT_EQ(0, header.generic->frame_id);
317 EXPECT_THAT(header.generic->dependencies, IsEmpty());
318
319 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
320 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
321 ASSERT_TRUE(header.generic);
322 EXPECT_EQ(1, header.generic->frame_id);
323 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
324}
325
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100326TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100327 RtpPayloadState state;
328 EncodedImage encoded_image;
329 CodecSpecificInfo codec_info;
330
Erik Språngcbc0cba2020-04-18 14:36:59 +0200331 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100332
333 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
334 codec_info.generic_frame_info =
335 GenericFrameInfo::Builder().S(1).T(0).Dtis("S").Build();
336 codec_info.generic_frame_info->encoder_buffers = {
337 {/*id=*/0, /*referenced=*/false, /*updated=*/true}};
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200338 codec_info.generic_frame_info->part_of_chain = {true, false};
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100339 RTPVideoHeader key_header =
340 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/1);
341
342 ASSERT_TRUE(key_header.generic);
343 EXPECT_EQ(key_header.generic->spatial_index, 1);
344 EXPECT_EQ(key_header.generic->temporal_index, 0);
345 EXPECT_EQ(key_header.generic->frame_id, 1);
346 EXPECT_THAT(key_header.generic->dependencies, IsEmpty());
347 EXPECT_THAT(key_header.generic->decode_target_indications,
348 ElementsAre(DecodeTargetIndication::kSwitch));
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200349 EXPECT_THAT(key_header.generic->chain_diffs, SizeIs(2));
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100350
351 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
352 codec_info.generic_frame_info =
353 GenericFrameInfo::Builder().S(2).T(3).Dtis("D").Build();
354 codec_info.generic_frame_info->encoder_buffers = {
355 {/*id=*/0, /*referenced=*/true, /*updated=*/false}};
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200356 codec_info.generic_frame_info->part_of_chain = {false, false};
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100357 RTPVideoHeader delta_header =
358 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/3);
359
360 ASSERT_TRUE(delta_header.generic);
361 EXPECT_EQ(delta_header.generic->spatial_index, 2);
362 EXPECT_EQ(delta_header.generic->temporal_index, 3);
363 EXPECT_EQ(delta_header.generic->frame_id, 3);
364 EXPECT_THAT(delta_header.generic->dependencies, ElementsAre(1));
365 EXPECT_THAT(delta_header.generic->decode_target_indications,
366 ElementsAre(DecodeTargetIndication::kDiscardable));
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200367 EXPECT_THAT(delta_header.generic->chain_diffs, SizeIs(2));
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100368}
369
philipelbf2b6202018-08-27 14:33:18 +0200370class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
371 public:
372 enum LayerSync { kNoSync, kSync };
373
philipel569397f2018-09-26 12:25:31 +0200374 RtpPayloadParamsVp8ToGenericTest()
Danil Chapovalov636865e2020-06-03 14:11:26 +0200375 : state_(), params_(123, &state_, trials_config_) {}
philipelbf2b6202018-08-27 14:33:18 +0200376
377 void ConvertAndCheck(int temporal_index,
378 int64_t shared_frame_id,
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000379 VideoFrameType frame_type,
philipelbf2b6202018-08-27 14:33:18 +0200380 LayerSync layer_sync,
philipelfab91292018-10-17 14:36:08 +0200381 const std::set<int64_t>& expected_deps,
382 uint16_t width = 0,
383 uint16_t height = 0) {
philipelbf2b6202018-08-27 14:33:18 +0200384 EncodedImage encoded_image;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000385 encoded_image._frameType = frame_type;
philipelfab91292018-10-17 14:36:08 +0200386 encoded_image._encodedWidth = width;
387 encoded_image._encodedHeight = height;
philipelbf2b6202018-08-27 14:33:18 +0200388
philipeld1d03592019-03-01 13:53:55 +0100389 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200390 codec_info.codecType = kVideoCodecVP8;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000391 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
392 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
philipelbf2b6202018-08-27 14:33:18 +0200393
394 RTPVideoHeader header =
395 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
396
397 ASSERT_TRUE(header.generic);
philipelbf2b6202018-08-27 14:33:18 +0200398 EXPECT_EQ(header.generic->spatial_index, 0);
399
400 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
401 EXPECT_EQ(header.generic->temporal_index, temporal_index);
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000402 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
403 header.generic->dependencies.end());
404 EXPECT_EQ(expected_deps, actual_deps);
philipelfab91292018-10-17 14:36:08 +0200405
406 EXPECT_EQ(header.width, width);
407 EXPECT_EQ(header.height, height);
philipelbf2b6202018-08-27 14:33:18 +0200408 }
409
410 protected:
Erik Språngcbc0cba2020-04-18 14:36:59 +0200411 FieldTrialBasedConfig trials_config_;
philipelbf2b6202018-08-27 14:33:18 +0200412 RtpPayloadState state_;
413 RtpPayloadParams params_;
414};
415
416TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000417 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
418 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
419 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200420}
421
422TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000423 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200424
425 EncodedImage encoded_image;
Niels Möller8f7ce222019-03-21 15:43:58 +0100426 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipeld1d03592019-03-01 13:53:55 +0100427 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200428 codec_info.codecType = kVideoCodecVP8;
429 codec_info.codecSpecific.VP8.temporalIdx =
430 RtpGenericFrameDescriptor::kMaxTemporalLayers;
431 codec_info.codecSpecific.VP8.layerSync = false;
432
433 RTPVideoHeader header =
434 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
435 EXPECT_FALSE(header.generic);
436}
437
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000438TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
439 // 02120212 pattern
440 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
441 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
442 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
443 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
philipelbf2b6202018-08-27 14:33:18 +0200444
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000445 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
446 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
447 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
448 {4}); // layer sync
449 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
philipelbf2b6202018-08-27 14:33:18 +0200450}
451
452TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
453 // 0101 pattern
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000454 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
455 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
philipelbf2b6202018-08-27 14:33:18 +0200456
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000457 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
458 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
philipelbf2b6202018-08-27 14:33:18 +0200459
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000460 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
461 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
philipelbf2b6202018-08-27 14:33:18 +0200462}
463
philipel8aba8fe2019-06-13 15:13:16 +0200464class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
465 public:
466 enum LayerSync { kNoSync, kSync };
467
468 RtpPayloadParamsH264ToGenericTest()
Danil Chapovalov636865e2020-06-03 14:11:26 +0200469 : state_(), params_(123, &state_, trials_config_) {}
philipel8aba8fe2019-06-13 15:13:16 +0200470
471 void ConvertAndCheck(int temporal_index,
472 int64_t shared_frame_id,
473 VideoFrameType frame_type,
474 LayerSync layer_sync,
475 const std::set<int64_t>& expected_deps,
476 uint16_t width = 0,
477 uint16_t height = 0) {
478 EncodedImage encoded_image;
479 encoded_image._frameType = frame_type;
480 encoded_image._encodedWidth = width;
481 encoded_image._encodedHeight = height;
482
483 CodecSpecificInfo codec_info;
484 codec_info.codecType = kVideoCodecH264;
485 codec_info.codecSpecific.H264.temporal_idx = temporal_index;
486 codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
487
488 RTPVideoHeader header =
489 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
490
491 ASSERT_TRUE(header.generic);
philipel8aba8fe2019-06-13 15:13:16 +0200492 EXPECT_EQ(header.generic->spatial_index, 0);
493
494 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
495 EXPECT_EQ(header.generic->temporal_index, temporal_index);
496 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
497 header.generic->dependencies.end());
498 EXPECT_EQ(expected_deps, actual_deps);
499
500 EXPECT_EQ(header.width, width);
501 EXPECT_EQ(header.height, height);
502 }
503
504 protected:
Erik Språngcbc0cba2020-04-18 14:36:59 +0200505 FieldTrialBasedConfig trials_config_;
philipel8aba8fe2019-06-13 15:13:16 +0200506 RtpPayloadState state_;
507 RtpPayloadParams params_;
508};
509
510TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
511 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
512 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
513 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
514}
515
516TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
517 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
518
519 EncodedImage encoded_image;
520 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
521 CodecSpecificInfo codec_info;
522 codec_info.codecType = kVideoCodecH264;
523 codec_info.codecSpecific.H264.temporal_idx =
524 RtpGenericFrameDescriptor::kMaxTemporalLayers;
525 codec_info.codecSpecific.H264.base_layer_sync = false;
526
527 RTPVideoHeader header =
528 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
529 EXPECT_FALSE(header.generic);
530}
531
532TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
533 // 02120212 pattern
534 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
535 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
536 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
537 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
538
539 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
540 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
541 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
542 {4}); // layer sync
543 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
544}
545
546TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
547 // 0101 pattern
548 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
549 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
550
551 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
552 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
553
554 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
555 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
556}
557
Stefan Holmerf7044682018-07-17 10:16:41 +0200558} // namespace webrtc