blob: 59c8f23bc20b19569328c6b3f23c91d20daa4183 [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"
Danil Chapovalovaf366442021-04-22 15:20:28 +020029#include "test/explicit_key_value_config.h"
philipelbf2b6202018-08-27 14:33:18 +020030#include "test/field_trial.h"
philipel8aba8fe2019-06-13 15:13:16 +020031#include "test/gmock.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020032#include "test/gtest.h"
33
Danil Chapovalovaf366442021-04-22 15:20:28 +020034using ::testing::Each;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010035using ::testing::ElementsAre;
36using ::testing::IsEmpty;
Danil Chapovalov4b860c12020-05-19 14:48:19 +020037using ::testing::SizeIs;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010038
Qingsi Wang1c1b99e2020-01-07 19:16:33 +000039namespace webrtc {
40namespace {
Stefan Holmerf7044682018-07-17 10:16:41 +020041const uint32_t kSsrc1 = 12345;
42const uint32_t kSsrc2 = 23456;
43const int16_t kPictureId = 123;
44const int16_t kTl0PicIdx = 20;
45const uint8_t kTemporalIdx = 1;
46const int16_t kInitialPictureId1 = 222;
47const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020048const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020049} // namespace
50
51TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
52 RtpPayloadState state2;
53 state2.picture_id = kPictureId;
54 state2.tl0_pic_idx = kTl0PicIdx;
55 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
56
Erik Språngcbc0cba2020-04-18 14:36:59 +020057 RtpPayloadParams params(kSsrc2, &state2, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020058 EncodedImage encoded_image;
59 encoded_image.rotation_ = kVideoRotation_90;
60 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020061 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020062
63 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020064 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020065 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020066 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020067 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020068 codec_info.codecSpecific.VP8.nonReference = true;
69
philipelbf2b6202018-08-27 14:33:18 +020070 RTPVideoHeader header =
71 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
72
73 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020074 codec_info.codecSpecific.VP8.temporalIdx = 1;
75 codec_info.codecSpecific.VP8.layerSync = true;
76
77 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020078
79 EXPECT_EQ(kVideoRotation_90, header.rotation);
80 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
81 EXPECT_EQ(1, header.simulcastIdx);
82 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +000083 const auto& vp8_header =
84 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
85 EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
86 EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
87 EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
88 EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
89 EXPECT_TRUE(vp8_header.layerSync);
90 EXPECT_TRUE(vp8_header.nonReference);
Stefan Holmerf7044682018-07-17 10:16:41 +020091}
92
93TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
94 RtpPayloadState state;
95 state.picture_id = kPictureId;
96 state.tl0_pic_idx = kTl0PicIdx;
Erik Språngcbc0cba2020-04-18 14:36:59 +020097 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020098
99 EncodedImage encoded_image;
100 encoded_image.rotation_ = kVideoRotation_90;
101 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200102 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +0200103 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200104 codec_info.codecType = kVideoCodecVP9;
105 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
106 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200107 codec_info.codecSpecific.VP9.temporal_idx = 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100108 codec_info.end_of_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200109
philipelbf2b6202018-08-27 14:33:18 +0200110 RTPVideoHeader header =
111 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200112
113 EXPECT_EQ(kVideoRotation_90, header.rotation);
114 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
115 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100116 EXPECT_FALSE(header.color_space);
philipel29d88462018-08-08 14:26:00 +0200117 const auto& vp9_header =
118 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
119 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
120 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
121 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200122 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200123 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200124 codec_info.codecSpecific.VP9.num_spatial_layers);
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100125 EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
Stefan Holmerf7044682018-07-17 10:16:41 +0200126
127 // Next spatial layer.
128 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100129 codec_info.end_of_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200130
Niels Möllerd3b8c632018-08-27 15:33:42 +0200131 encoded_image.SetSpatialIndex(1);
Johannes Krond0b69a82018-12-03 14:18:53 +0100132 ColorSpace color_space(
133 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
134 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
Danil Chapovalovb7698942019-02-05 11:32:19 +0100135 encoded_image.SetColorSpace(color_space);
philipelbf2b6202018-08-27 14:33:18 +0200136 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200137
138 EXPECT_EQ(kVideoRotation_90, header.rotation);
139 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
140 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100141 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
philipel29d88462018-08-08 14:26:00 +0200142 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
143 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
144 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200145 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200146 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200147 codec_info.codecSpecific.VP9.num_spatial_layers);
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100148 EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
Stefan Holmerf7044682018-07-17 10:16:41 +0200149}
150
Stefan Holmerf7044682018-07-17 10:16:41 +0200151TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
152 RtpPayloadState state;
153 state.picture_id = kInitialPictureId1;
154 state.tl0_pic_idx = kInitialTl0PicIdx1;
155
156 EncodedImage encoded_image;
157 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200158 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200159
Erik Språngcbc0cba2020-04-18 14:36:59 +0200160 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200161 RTPVideoHeader header =
162 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200163 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000164 EXPECT_EQ(kInitialPictureId1 + 1,
165 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200166
167 // State should hold latest used picture id and tl0_pic_idx.
168 state = params.state();
169 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
170 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
171}
172
173TEST(RtpPayloadParamsTest, PictureIdWraps) {
174 RtpPayloadState state;
175 state.picture_id = kMaxTwoBytePictureId;
176 state.tl0_pic_idx = kInitialTl0PicIdx1;
177
178 EncodedImage encoded_image;
179 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200180 codec_info.codecType = kVideoCodecVP8;
181 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
182
Erik Språngcbc0cba2020-04-18 14:36:59 +0200183 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200184 RTPVideoHeader header =
185 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200186 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000187 EXPECT_EQ(0,
188 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200189
190 // State should hold latest used picture id and tl0_pic_idx.
191 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
192 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
193}
194
195TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
196 RtpPayloadState state;
197 state.picture_id = kInitialPictureId1;
198 state.tl0_pic_idx = kInitialTl0PicIdx1;
199
200 EncodedImage encoded_image;
201 // Modules are sending for this test.
202 // OnEncodedImage, temporalIdx: 1.
203 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200204 codec_info.codecType = kVideoCodecVP8;
205 codec_info.codecSpecific.VP8.temporalIdx = 1;
206
Erik Språngcbc0cba2020-04-18 14:36:59 +0200207 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200208 RTPVideoHeader header =
209 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200210
211 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000212 const auto& vp8_header =
213 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
214 EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
215 EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200216
217 // OnEncodedImage, temporalIdx: 0.
218 codec_info.codecSpecific.VP8.temporalIdx = 0;
219
philipelbf2b6202018-08-27 14:33:18 +0200220 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200221 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000222 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
223 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200224
225 // State should hold latest used picture id and tl0_pic_idx.
226 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
227 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
228}
229
230TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
231 RtpPayloadState state;
232 state.picture_id = kInitialPictureId1;
233 state.tl0_pic_idx = kInitialTl0PicIdx1;
234
235 EncodedImage encoded_image;
236 // Modules are sending for this test.
237 // OnEncodedImage, temporalIdx: 1.
238 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200239 codec_info.codecType = kVideoCodecVP9;
240 codec_info.codecSpecific.VP9.temporal_idx = 1;
241 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
242
Erik Språngcbc0cba2020-04-18 14:36:59 +0200243 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200244 RTPVideoHeader header =
245 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200246
247 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200248 const auto& vp9_header =
249 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
250 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
251 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200252
253 // OnEncodedImage, temporalIdx: 0.
254 codec_info.codecSpecific.VP9.temporal_idx = 0;
255
philipelbf2b6202018-08-27 14:33:18 +0200256 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200257
258 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200259 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
260 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200261
262 // OnEncodedImage, first_frame_in_picture = false
263 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
264
philipelbf2b6202018-08-27 14:33:18 +0200265 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200266
267 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200268 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
269 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200270
271 // State should hold latest used picture id and tl0_pic_idx.
272 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
273 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
274}
philipelbf2b6202018-08-27 14:33:18 +0200275
276TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
277 test::ScopedFieldTrials generic_picture_id(
278 "WebRTC-GenericPictureId/Enabled/");
279 RtpPayloadState state{};
280
281 EncodedImage encoded_image;
philipeld1d03592019-03-01 13:53:55 +0100282 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200283 codec_info.codecType = kVideoCodecGeneric;
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100284 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
philipelbf2b6202018-08-27 14:33:18 +0200285
Erik Språngcbc0cba2020-04-18 14:36:59 +0200286 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200287 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100288 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
philipelbf2b6202018-08-27 14:33:18 +0200289
290 EXPECT_EQ(kVideoCodecGeneric, header.codec);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100291 const auto* generic =
292 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
293 ASSERT_TRUE(generic);
294 EXPECT_EQ(0, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200295
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100296 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
297 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100298 generic =
299 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
300 ASSERT_TRUE(generic);
301 EXPECT_EQ(1, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200302}
303
philipel8aba8fe2019-06-13 15:13:16 +0200304TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
philipel8aba8fe2019-06-13 15:13:16 +0200305 RtpPayloadState state{};
306
307 EncodedImage encoded_image;
308 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
309 CodecSpecificInfo codec_info;
310 codec_info.codecType = kVideoCodecGeneric;
311
Erik Språngcbc0cba2020-04-18 14:36:59 +0200312 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipel8aba8fe2019-06-13 15:13:16 +0200313 RTPVideoHeader header =
314 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
315
316 EXPECT_EQ(kVideoCodecGeneric, header.codec);
317 ASSERT_TRUE(header.generic);
318 EXPECT_EQ(0, header.generic->frame_id);
319 EXPECT_THAT(header.generic->dependencies, IsEmpty());
320
321 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
322 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
323 ASSERT_TRUE(header.generic);
324 EXPECT_EQ(1, header.generic->frame_id);
325 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
326}
327
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100328TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100329 RtpPayloadState state;
330 EncodedImage encoded_image;
331 CodecSpecificInfo codec_info;
332
Erik Språngcbc0cba2020-04-18 14:36:59 +0200333 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100334
335 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
336 codec_info.generic_frame_info =
337 GenericFrameInfo::Builder().S(1).T(0).Dtis("S").Build();
338 codec_info.generic_frame_info->encoder_buffers = {
339 {/*id=*/0, /*referenced=*/false, /*updated=*/true}};
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200340 codec_info.generic_frame_info->part_of_chain = {true, false};
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100341 RTPVideoHeader key_header =
342 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/1);
343
344 ASSERT_TRUE(key_header.generic);
345 EXPECT_EQ(key_header.generic->spatial_index, 1);
346 EXPECT_EQ(key_header.generic->temporal_index, 0);
347 EXPECT_EQ(key_header.generic->frame_id, 1);
348 EXPECT_THAT(key_header.generic->dependencies, IsEmpty());
349 EXPECT_THAT(key_header.generic->decode_target_indications,
350 ElementsAre(DecodeTargetIndication::kSwitch));
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200351 EXPECT_THAT(key_header.generic->chain_diffs, SizeIs(2));
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100352
353 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
354 codec_info.generic_frame_info =
355 GenericFrameInfo::Builder().S(2).T(3).Dtis("D").Build();
356 codec_info.generic_frame_info->encoder_buffers = {
357 {/*id=*/0, /*referenced=*/true, /*updated=*/false}};
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200358 codec_info.generic_frame_info->part_of_chain = {false, false};
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100359 RTPVideoHeader delta_header =
360 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/3);
361
362 ASSERT_TRUE(delta_header.generic);
363 EXPECT_EQ(delta_header.generic->spatial_index, 2);
364 EXPECT_EQ(delta_header.generic->temporal_index, 3);
365 EXPECT_EQ(delta_header.generic->frame_id, 3);
366 EXPECT_THAT(delta_header.generic->dependencies, ElementsAre(1));
367 EXPECT_THAT(delta_header.generic->decode_target_indications,
368 ElementsAre(DecodeTargetIndication::kDiscardable));
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200369 EXPECT_THAT(delta_header.generic->chain_diffs, SizeIs(2));
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100370}
371
philipelbf2b6202018-08-27 14:33:18 +0200372class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
373 public:
374 enum LayerSync { kNoSync, kSync };
375
philipel569397f2018-09-26 12:25:31 +0200376 RtpPayloadParamsVp8ToGenericTest()
Danil Chapovalov636865e2020-06-03 14:11:26 +0200377 : state_(), params_(123, &state_, trials_config_) {}
philipelbf2b6202018-08-27 14:33:18 +0200378
379 void ConvertAndCheck(int temporal_index,
380 int64_t shared_frame_id,
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000381 VideoFrameType frame_type,
philipelbf2b6202018-08-27 14:33:18 +0200382 LayerSync layer_sync,
philipelfab91292018-10-17 14:36:08 +0200383 const std::set<int64_t>& expected_deps,
384 uint16_t width = 0,
385 uint16_t height = 0) {
philipelbf2b6202018-08-27 14:33:18 +0200386 EncodedImage encoded_image;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000387 encoded_image._frameType = frame_type;
philipelfab91292018-10-17 14:36:08 +0200388 encoded_image._encodedWidth = width;
389 encoded_image._encodedHeight = height;
philipelbf2b6202018-08-27 14:33:18 +0200390
philipeld1d03592019-03-01 13:53:55 +0100391 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200392 codec_info.codecType = kVideoCodecVP8;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000393 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
394 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
philipelbf2b6202018-08-27 14:33:18 +0200395
396 RTPVideoHeader header =
397 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
398
399 ASSERT_TRUE(header.generic);
philipelbf2b6202018-08-27 14:33:18 +0200400 EXPECT_EQ(header.generic->spatial_index, 0);
401
402 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
403 EXPECT_EQ(header.generic->temporal_index, temporal_index);
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000404 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
405 header.generic->dependencies.end());
406 EXPECT_EQ(expected_deps, actual_deps);
philipelfab91292018-10-17 14:36:08 +0200407
408 EXPECT_EQ(header.width, width);
409 EXPECT_EQ(header.height, height);
philipelbf2b6202018-08-27 14:33:18 +0200410 }
411
412 protected:
Erik Språngcbc0cba2020-04-18 14:36:59 +0200413 FieldTrialBasedConfig trials_config_;
philipelbf2b6202018-08-27 14:33:18 +0200414 RtpPayloadState state_;
415 RtpPayloadParams params_;
416};
417
418TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000419 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
420 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
421 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200422}
423
424TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000425 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200426
427 EncodedImage encoded_image;
Niels Möller8f7ce222019-03-21 15:43:58 +0100428 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipeld1d03592019-03-01 13:53:55 +0100429 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200430 codec_info.codecType = kVideoCodecVP8;
431 codec_info.codecSpecific.VP8.temporalIdx =
432 RtpGenericFrameDescriptor::kMaxTemporalLayers;
433 codec_info.codecSpecific.VP8.layerSync = false;
434
435 RTPVideoHeader header =
436 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
437 EXPECT_FALSE(header.generic);
438}
439
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000440TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
441 // 02120212 pattern
442 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
443 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
444 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
445 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
philipelbf2b6202018-08-27 14:33:18 +0200446
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000447 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
448 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
449 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
450 {4}); // layer sync
451 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
philipelbf2b6202018-08-27 14:33:18 +0200452}
453
454TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
455 // 0101 pattern
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000456 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
457 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
philipelbf2b6202018-08-27 14:33:18 +0200458
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000459 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
460 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
philipelbf2b6202018-08-27 14:33:18 +0200461
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000462 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
463 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
philipelbf2b6202018-08-27 14:33:18 +0200464}
465
Emil Lundmarkb0628292021-07-28 13:04:36 +0200466TEST(RtpPayloadParamsVp9ToGenericTest, NoScalability) {
467 RtpPayloadState state;
468 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
Danil Chapovalovaf366442021-04-22 15:20:28 +0200469
470 EncodedImage encoded_image;
471 CodecSpecificInfo codec_info;
472 codec_info.codecType = kVideoCodecVP9;
473 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
474 codec_info.codecSpecific.VP9.temporal_idx = kNoTemporalIdx;
475 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
476 codec_info.end_of_picture = true;
477
478 // Key frame.
479 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
480 codec_info.codecSpecific.VP9.inter_pic_predicted = false;
481 codec_info.codecSpecific.VP9.num_ref_pics = 0;
482 RTPVideoHeader header = params.GetRtpVideoHeader(encoded_image, &codec_info,
483 /*shared_frame_id=*/1);
484
485 ASSERT_TRUE(header.generic);
486 EXPECT_EQ(header.generic->spatial_index, 0);
487 EXPECT_EQ(header.generic->temporal_index, 0);
488 EXPECT_EQ(header.generic->frame_id, 1);
489 ASSERT_THAT(header.generic->decode_target_indications, Not(IsEmpty()));
490 EXPECT_EQ(header.generic->decode_target_indications[0],
491 DecodeTargetIndication::kSwitch);
492 EXPECT_THAT(header.generic->dependencies, IsEmpty());
493 EXPECT_THAT(header.generic->chain_diffs, ElementsAre(0));
494
495 // Delta frame.
496 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
497 codec_info.codecSpecific.VP9.inter_pic_predicted = true;
498 codec_info.codecSpecific.VP9.num_ref_pics = 1;
499 codec_info.codecSpecific.VP9.p_diff[0] = 1;
500 header = params.GetRtpVideoHeader(encoded_image, &codec_info,
501 /*shared_frame_id=*/3);
502
503 ASSERT_TRUE(header.generic);
504 EXPECT_EQ(header.generic->spatial_index, 0);
505 EXPECT_EQ(header.generic->temporal_index, 0);
506 EXPECT_EQ(header.generic->frame_id, 3);
507 ASSERT_THAT(header.generic->decode_target_indications, Not(IsEmpty()));
508 EXPECT_EQ(header.generic->decode_target_indications[0],
509 DecodeTargetIndication::kSwitch);
510 EXPECT_THAT(header.generic->dependencies, ElementsAre(1));
511 // previous frame in the chain was frame#1,
512 EXPECT_THAT(header.generic->chain_diffs, ElementsAre(3 - 1));
513}
514
Emil Lundmarkb0628292021-07-28 13:04:36 +0200515TEST(RtpPayloadParamsVp9ToGenericTest, TemporalScalabilityWith2Layers) {
Danil Chapovalovaf366442021-04-22 15:20:28 +0200516 // Test with 2 temporal layers structure that is not used by webrtc:
517 // 1---3 5
518 // / / / ...
519 // 0---2---4---
Emil Lundmarkb0628292021-07-28 13:04:36 +0200520 RtpPayloadState state;
521 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
Danil Chapovalovaf366442021-04-22 15:20:28 +0200522
523 EncodedImage image;
524 CodecSpecificInfo info;
525 info.codecType = kVideoCodecVP9;
526 info.codecSpecific.VP9.num_spatial_layers = 1;
527 info.codecSpecific.VP9.first_frame_in_picture = true;
528 info.end_of_picture = true;
529
530 RTPVideoHeader headers[6];
531 // Key frame.
532 image._frameType = VideoFrameType::kVideoFrameKey;
533 info.codecSpecific.VP9.inter_pic_predicted = false;
534 info.codecSpecific.VP9.num_ref_pics = 0;
535 info.codecSpecific.VP9.temporal_up_switch = true;
536 info.codecSpecific.VP9.temporal_idx = 0;
537 headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
538
539 // Delta frames.
540 info.codecSpecific.VP9.inter_pic_predicted = true;
541 image._frameType = VideoFrameType::kVideoFrameDelta;
542
543 info.codecSpecific.VP9.temporal_up_switch = true;
544 info.codecSpecific.VP9.temporal_idx = 1;
545 info.codecSpecific.VP9.num_ref_pics = 1;
546 info.codecSpecific.VP9.p_diff[0] = 1;
547 headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
548
549 info.codecSpecific.VP9.temporal_up_switch = false;
550 info.codecSpecific.VP9.temporal_idx = 0;
551 info.codecSpecific.VP9.num_ref_pics = 1;
552 info.codecSpecific.VP9.p_diff[0] = 2;
553 headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
554
555 info.codecSpecific.VP9.temporal_up_switch = false;
556 info.codecSpecific.VP9.temporal_idx = 1;
557 info.codecSpecific.VP9.num_ref_pics = 2;
558 info.codecSpecific.VP9.p_diff[0] = 1;
559 info.codecSpecific.VP9.p_diff[1] = 2;
560 headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
561
562 info.codecSpecific.VP9.temporal_up_switch = true;
563 info.codecSpecific.VP9.temporal_idx = 0;
564 info.codecSpecific.VP9.num_ref_pics = 1;
565 info.codecSpecific.VP9.p_diff[0] = 2;
566 headers[4] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/9);
567
568 info.codecSpecific.VP9.temporal_up_switch = true;
569 info.codecSpecific.VP9.temporal_idx = 1;
570 info.codecSpecific.VP9.num_ref_pics = 1;
571 info.codecSpecific.VP9.p_diff[0] = 1;
572 headers[5] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/11);
573
574 ASSERT_TRUE(headers[0].generic);
575 int num_decode_targets = headers[0].generic->decode_target_indications.size();
576 ASSERT_GE(num_decode_targets, 2);
577
578 for (int frame_idx = 0; frame_idx < 6; ++frame_idx) {
579 const RTPVideoHeader& header = headers[frame_idx];
580 ASSERT_TRUE(header.generic);
581 EXPECT_EQ(header.generic->spatial_index, 0);
582 EXPECT_EQ(header.generic->temporal_index, frame_idx % 2);
583 EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
584 ASSERT_THAT(header.generic->decode_target_indications,
585 SizeIs(num_decode_targets));
586 // Expect only T0 frames are needed for the 1st decode target.
587 if (header.generic->temporal_index == 0) {
588 EXPECT_NE(header.generic->decode_target_indications[0],
589 DecodeTargetIndication::kNotPresent);
590 } else {
591 EXPECT_EQ(header.generic->decode_target_indications[0],
592 DecodeTargetIndication::kNotPresent);
593 }
594 // Expect all frames are needed for the 2nd decode target.
595 EXPECT_NE(header.generic->decode_target_indications[1],
596 DecodeTargetIndication::kNotPresent);
597 }
598
599 // Expect switch at every beginning of the pattern.
600 EXPECT_THAT(headers[0].generic->decode_target_indications,
601 Each(DecodeTargetIndication::kSwitch));
602 EXPECT_THAT(headers[4].generic->decode_target_indications,
603 Each(DecodeTargetIndication::kSwitch));
604
605 EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // T0, 1
606 EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // T1, 3
607 EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // T0, 5
608 EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(5, 3)); // T1, 7
609 EXPECT_THAT(headers[4].generic->dependencies, ElementsAre(5)); // T0, 9
610 EXPECT_THAT(headers[5].generic->dependencies, ElementsAre(9)); // T1, 11
611
612 EXPECT_THAT(headers[0].generic->chain_diffs, ElementsAre(0));
613 EXPECT_THAT(headers[1].generic->chain_diffs, ElementsAre(2));
614 EXPECT_THAT(headers[2].generic->chain_diffs, ElementsAre(4));
615 EXPECT_THAT(headers[3].generic->chain_diffs, ElementsAre(2));
616 EXPECT_THAT(headers[4].generic->chain_diffs, ElementsAre(4));
617 EXPECT_THAT(headers[5].generic->chain_diffs, ElementsAre(2));
618}
619
Emil Lundmarkb0628292021-07-28 13:04:36 +0200620TEST(RtpPayloadParamsVp9ToGenericTest, TemporalScalabilityWith3Layers) {
Danil Chapovalovaf366442021-04-22 15:20:28 +0200621 // Test with 3 temporal layers structure that is not used by webrtc, but used
622 // by chromium: https://imgur.com/pURAGvp
Emil Lundmarkb0628292021-07-28 13:04:36 +0200623 RtpPayloadState state;
624 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
Danil Chapovalovaf366442021-04-22 15:20:28 +0200625
626 EncodedImage image;
627 CodecSpecificInfo info;
628 info.codecType = kVideoCodecVP9;
629 info.codecSpecific.VP9.num_spatial_layers = 1;
630 info.codecSpecific.VP9.first_frame_in_picture = true;
631 info.end_of_picture = true;
632
633 RTPVideoHeader headers[9];
634 // Key frame.
635 image._frameType = VideoFrameType::kVideoFrameKey;
636 info.codecSpecific.VP9.inter_pic_predicted = false;
637 info.codecSpecific.VP9.num_ref_pics = 0;
638 info.codecSpecific.VP9.temporal_up_switch = true;
639 info.codecSpecific.VP9.temporal_idx = 0;
640 headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
641
642 // Delta frames.
643 info.codecSpecific.VP9.inter_pic_predicted = true;
644 image._frameType = VideoFrameType::kVideoFrameDelta;
645
646 info.codecSpecific.VP9.temporal_up_switch = true;
647 info.codecSpecific.VP9.temporal_idx = 2;
648 info.codecSpecific.VP9.num_ref_pics = 1;
649 info.codecSpecific.VP9.p_diff[0] = 1;
650 headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
651
652 info.codecSpecific.VP9.temporal_up_switch = true;
653 info.codecSpecific.VP9.temporal_idx = 1;
654 info.codecSpecific.VP9.num_ref_pics = 1;
655 info.codecSpecific.VP9.p_diff[0] = 2;
656 headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
657
658 info.codecSpecific.VP9.temporal_up_switch = true;
659 info.codecSpecific.VP9.temporal_idx = 2;
660 info.codecSpecific.VP9.num_ref_pics = 1;
661 info.codecSpecific.VP9.p_diff[0] = 1;
662 headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
663
664 info.codecSpecific.VP9.temporal_up_switch = false;
665 info.codecSpecific.VP9.temporal_idx = 0;
666 info.codecSpecific.VP9.num_ref_pics = 1;
667 info.codecSpecific.VP9.p_diff[0] = 4;
668 headers[4] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/9);
669
670 info.codecSpecific.VP9.temporal_up_switch = true;
671 info.codecSpecific.VP9.temporal_idx = 2;
672 info.codecSpecific.VP9.num_ref_pics = 2;
673 info.codecSpecific.VP9.p_diff[0] = 1;
674 info.codecSpecific.VP9.p_diff[1] = 3;
675 headers[5] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/11);
676
677 info.codecSpecific.VP9.temporal_up_switch = false;
678 info.codecSpecific.VP9.temporal_idx = 1;
679 info.codecSpecific.VP9.num_ref_pics = 2;
680 info.codecSpecific.VP9.p_diff[0] = 2;
681 info.codecSpecific.VP9.p_diff[1] = 4;
682 headers[6] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/13);
683
684 info.codecSpecific.VP9.temporal_up_switch = true;
685 info.codecSpecific.VP9.temporal_idx = 2;
686 info.codecSpecific.VP9.num_ref_pics = 1;
687 info.codecSpecific.VP9.p_diff[0] = 1;
688 headers[7] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/15);
689
690 info.codecSpecific.VP9.temporal_up_switch = true;
691 info.codecSpecific.VP9.temporal_idx = 0;
692 info.codecSpecific.VP9.num_ref_pics = 1;
693 info.codecSpecific.VP9.p_diff[0] = 4;
694 headers[8] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/17);
695
696 ASSERT_TRUE(headers[0].generic);
697 int num_decode_targets = headers[0].generic->decode_target_indications.size();
698 ASSERT_GE(num_decode_targets, 3);
699
700 for (int frame_idx = 0; frame_idx < 9; ++frame_idx) {
701 const RTPVideoHeader& header = headers[frame_idx];
702 ASSERT_TRUE(header.generic);
703 EXPECT_EQ(header.generic->spatial_index, 0);
704 EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
705 ASSERT_THAT(header.generic->decode_target_indications,
706 SizeIs(num_decode_targets));
707 // Expect only T0 frames are needed for the 1st decode target.
708 if (header.generic->temporal_index == 0) {
709 EXPECT_NE(header.generic->decode_target_indications[0],
710 DecodeTargetIndication::kNotPresent);
711 } else {
712 EXPECT_EQ(header.generic->decode_target_indications[0],
713 DecodeTargetIndication::kNotPresent);
714 }
715 // Expect only T0 and T1 frames are needed for the 2nd decode target.
716 if (header.generic->temporal_index <= 1) {
717 EXPECT_NE(header.generic->decode_target_indications[1],
718 DecodeTargetIndication::kNotPresent);
719 } else {
720 EXPECT_EQ(header.generic->decode_target_indications[1],
721 DecodeTargetIndication::kNotPresent);
722 }
723 // Expect all frames are needed for the 3rd decode target.
724 EXPECT_NE(header.generic->decode_target_indications[2],
725 DecodeTargetIndication::kNotPresent);
726 }
727
728 EXPECT_EQ(headers[0].generic->temporal_index, 0);
729 EXPECT_EQ(headers[1].generic->temporal_index, 2);
730 EXPECT_EQ(headers[2].generic->temporal_index, 1);
731 EXPECT_EQ(headers[3].generic->temporal_index, 2);
732 EXPECT_EQ(headers[4].generic->temporal_index, 0);
733 EXPECT_EQ(headers[5].generic->temporal_index, 2);
734 EXPECT_EQ(headers[6].generic->temporal_index, 1);
735 EXPECT_EQ(headers[7].generic->temporal_index, 2);
736 EXPECT_EQ(headers[8].generic->temporal_index, 0);
737
738 // Expect switch at every beginning of the pattern.
739 EXPECT_THAT(headers[0].generic->decode_target_indications,
740 Each(DecodeTargetIndication::kSwitch));
741 EXPECT_THAT(headers[8].generic->decode_target_indications,
742 Each(DecodeTargetIndication::kSwitch));
743
744 EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // T0, 1
745 EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // T2, 3
746 EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // T1, 5
747 EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(5)); // T2, 7
748 EXPECT_THAT(headers[4].generic->dependencies, ElementsAre(1)); // T0, 9
749 EXPECT_THAT(headers[5].generic->dependencies, ElementsAre(9, 5)); // T2, 11
750 EXPECT_THAT(headers[6].generic->dependencies, ElementsAre(9, 5)); // T1, 13
751 EXPECT_THAT(headers[7].generic->dependencies, ElementsAre(13)); // T2, 15
752 EXPECT_THAT(headers[8].generic->dependencies, ElementsAre(9)); // T0, 17
753
754 EXPECT_THAT(headers[0].generic->chain_diffs, ElementsAre(0));
755 EXPECT_THAT(headers[1].generic->chain_diffs, ElementsAre(2));
756 EXPECT_THAT(headers[2].generic->chain_diffs, ElementsAre(4));
757 EXPECT_THAT(headers[3].generic->chain_diffs, ElementsAre(6));
758 EXPECT_THAT(headers[4].generic->chain_diffs, ElementsAre(8));
759 EXPECT_THAT(headers[5].generic->chain_diffs, ElementsAre(2));
760 EXPECT_THAT(headers[6].generic->chain_diffs, ElementsAre(4));
761 EXPECT_THAT(headers[7].generic->chain_diffs, ElementsAre(6));
762 EXPECT_THAT(headers[8].generic->chain_diffs, ElementsAre(8));
763}
764
Emil Lundmarkb0628292021-07-28 13:04:36 +0200765TEST(RtpPayloadParamsVp9ToGenericTest, SpatialScalabilityKSvc) {
Danil Chapovalovaf366442021-04-22 15:20:28 +0200766 // 1---3--
767 // | ...
768 // 0---2--
Emil Lundmarkb0628292021-07-28 13:04:36 +0200769 RtpPayloadState state;
770 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
Danil Chapovalovaf366442021-04-22 15:20:28 +0200771
772 EncodedImage image;
773 CodecSpecificInfo info;
774 info.codecType = kVideoCodecVP9;
775 info.codecSpecific.VP9.num_spatial_layers = 2;
776 info.codecSpecific.VP9.first_frame_in_picture = true;
777
778 RTPVideoHeader headers[4];
779 // Key frame.
780 image._frameType = VideoFrameType::kVideoFrameKey;
781 image.SetSpatialIndex(0);
782 info.codecSpecific.VP9.inter_pic_predicted = false;
783 info.codecSpecific.VP9.inter_layer_predicted = false;
784 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = false;
785 info.codecSpecific.VP9.num_ref_pics = 0;
786 info.codecSpecific.VP9.first_frame_in_picture = true;
787 info.end_of_picture = false;
788 headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
789
790 image.SetSpatialIndex(1);
791 info.codecSpecific.VP9.inter_layer_predicted = true;
792 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
793 info.codecSpecific.VP9.first_frame_in_picture = false;
794 info.end_of_picture = true;
795 headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
796
797 // Delta frames.
798 info.codecSpecific.VP9.inter_pic_predicted = true;
799 image._frameType = VideoFrameType::kVideoFrameDelta;
800 info.codecSpecific.VP9.num_ref_pics = 1;
801 info.codecSpecific.VP9.p_diff[0] = 1;
802
803 image.SetSpatialIndex(0);
804 info.codecSpecific.VP9.inter_layer_predicted = false;
805 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
806 info.codecSpecific.VP9.first_frame_in_picture = true;
807 info.end_of_picture = false;
808 headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
809
810 image.SetSpatialIndex(1);
811 info.codecSpecific.VP9.inter_layer_predicted = false;
812 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
813 info.codecSpecific.VP9.first_frame_in_picture = false;
814 info.end_of_picture = true;
815 headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
816
817 ASSERT_TRUE(headers[0].generic);
818 int num_decode_targets = headers[0].generic->decode_target_indications.size();
819 // Rely on implementation detail there are always kMaxTemporalStreams temporal
820 // layers assumed, in particular assume Decode Target#0 matches layer S0T0,
821 // and Decode Target#kMaxTemporalStreams matches layer S1T0.
822 ASSERT_EQ(num_decode_targets, kMaxTemporalStreams * 2);
823
824 for (int frame_idx = 0; frame_idx < 4; ++frame_idx) {
825 const RTPVideoHeader& header = headers[frame_idx];
826 ASSERT_TRUE(header.generic);
827 EXPECT_EQ(header.generic->spatial_index, frame_idx % 2);
828 EXPECT_EQ(header.generic->temporal_index, 0);
829 EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
830 ASSERT_THAT(header.generic->decode_target_indications,
831 SizeIs(num_decode_targets));
832 }
833
834 // Expect S0 key frame is switch for both Decode Targets.
835 EXPECT_EQ(headers[0].generic->decode_target_indications[0],
836 DecodeTargetIndication::kSwitch);
837 EXPECT_EQ(headers[0].generic->decode_target_indications[kMaxTemporalStreams],
838 DecodeTargetIndication::kSwitch);
839 // S1 key frame is only needed for the 2nd Decode Targets.
840 EXPECT_EQ(headers[1].generic->decode_target_indications[0],
841 DecodeTargetIndication::kNotPresent);
842 EXPECT_NE(headers[1].generic->decode_target_indications[kMaxTemporalStreams],
843 DecodeTargetIndication::kNotPresent);
844 // Delta frames are only needed for their own Decode Targets.
845 EXPECT_NE(headers[2].generic->decode_target_indications[0],
846 DecodeTargetIndication::kNotPresent);
847 EXPECT_EQ(headers[2].generic->decode_target_indications[kMaxTemporalStreams],
848 DecodeTargetIndication::kNotPresent);
849 EXPECT_EQ(headers[3].generic->decode_target_indications[0],
850 DecodeTargetIndication::kNotPresent);
851 EXPECT_NE(headers[3].generic->decode_target_indications[kMaxTemporalStreams],
852 DecodeTargetIndication::kNotPresent);
853
854 EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // S0, 1
855 EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // S1, 3
856 EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // S0, 5
857 EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(3)); // S1, 7
858
859 EXPECT_THAT(headers[0].generic->chain_diffs, ElementsAre(0, 0));
860 EXPECT_THAT(headers[1].generic->chain_diffs, ElementsAre(2, 2));
861 EXPECT_THAT(headers[2].generic->chain_diffs, ElementsAre(4, 2));
862 EXPECT_THAT(headers[3].generic->chain_diffs, ElementsAre(2, 4));
863}
864
philipel8aba8fe2019-06-13 15:13:16 +0200865class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
866 public:
867 enum LayerSync { kNoSync, kSync };
868
869 RtpPayloadParamsH264ToGenericTest()
Danil Chapovalov636865e2020-06-03 14:11:26 +0200870 : state_(), params_(123, &state_, trials_config_) {}
philipel8aba8fe2019-06-13 15:13:16 +0200871
872 void ConvertAndCheck(int temporal_index,
873 int64_t shared_frame_id,
874 VideoFrameType frame_type,
875 LayerSync layer_sync,
876 const std::set<int64_t>& expected_deps,
877 uint16_t width = 0,
878 uint16_t height = 0) {
879 EncodedImage encoded_image;
880 encoded_image._frameType = frame_type;
881 encoded_image._encodedWidth = width;
882 encoded_image._encodedHeight = height;
883
884 CodecSpecificInfo codec_info;
885 codec_info.codecType = kVideoCodecH264;
886 codec_info.codecSpecific.H264.temporal_idx = temporal_index;
887 codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
888
889 RTPVideoHeader header =
890 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
891
892 ASSERT_TRUE(header.generic);
philipel8aba8fe2019-06-13 15:13:16 +0200893 EXPECT_EQ(header.generic->spatial_index, 0);
894
895 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
896 EXPECT_EQ(header.generic->temporal_index, temporal_index);
897 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
898 header.generic->dependencies.end());
899 EXPECT_EQ(expected_deps, actual_deps);
900
901 EXPECT_EQ(header.width, width);
902 EXPECT_EQ(header.height, height);
903 }
904
905 protected:
Erik Språngcbc0cba2020-04-18 14:36:59 +0200906 FieldTrialBasedConfig trials_config_;
philipel8aba8fe2019-06-13 15:13:16 +0200907 RtpPayloadState state_;
908 RtpPayloadParams params_;
909};
910
911TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
912 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
913 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
914 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
915}
916
917TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
918 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
919
920 EncodedImage encoded_image;
921 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
922 CodecSpecificInfo codec_info;
923 codec_info.codecType = kVideoCodecH264;
924 codec_info.codecSpecific.H264.temporal_idx =
925 RtpGenericFrameDescriptor::kMaxTemporalLayers;
926 codec_info.codecSpecific.H264.base_layer_sync = false;
927
928 RTPVideoHeader header =
929 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
930 EXPECT_FALSE(header.generic);
931}
932
933TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
934 // 02120212 pattern
935 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
936 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
937 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
938 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
939
940 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
941 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
942 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
943 {4}); // layer sync
944 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
945}
946
947TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
948 // 0101 pattern
949 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
950 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
951
952 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
953 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
954
955 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
956 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
957}
958
Stefan Holmerf7044682018-07-17 10:16:41 +0200959} // namespace webrtc