blob: 6a54ac8f9fc62e4996411772063beb46d51e801c [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"
philipel8aba8fe2019-06-13 15:13:16 +020030#include "test/gmock.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020031#include "test/gtest.h"
Jonas Orelandc7f691a2022-03-09 15:12:07 +010032#include "test/scoped_key_value_config.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020033
Emil Lundmark6c81a422022-05-18 17:13:34 +020034namespace webrtc {
35namespace {
36
37using ::testing::AllOf;
Danil Chapovalovaf366442021-04-22 15:20:28 +020038using ::testing::Each;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010039using ::testing::ElementsAre;
philipel5b231de2021-09-01 15:21:16 +020040using ::testing::Eq;
Emil Lundmark6c81a422022-05-18 17:13:34 +020041using ::testing::Field;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010042using ::testing::IsEmpty;
Emil Lundmark6c81a422022-05-18 17:13:34 +020043using ::testing::Optional;
Danil Chapovalov4b860c12020-05-19 14:48:19 +020044using ::testing::SizeIs;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010045
Emil Lundmark6c81a422022-05-18 17:13:34 +020046using GenericDescriptorInfo = RTPVideoHeader::GenericDescriptorInfo;
47
Stefan Holmerf7044682018-07-17 10:16:41 +020048const uint32_t kSsrc1 = 12345;
49const uint32_t kSsrc2 = 23456;
50const int16_t kPictureId = 123;
51const int16_t kTl0PicIdx = 20;
52const uint8_t kTemporalIdx = 1;
53const int16_t kInitialPictureId1 = 222;
54const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020055const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020056
57TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
58 RtpPayloadState state2;
59 state2.picture_id = kPictureId;
60 state2.tl0_pic_idx = kTl0PicIdx;
61 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
62
Erik Språngcbc0cba2020-04-18 14:36:59 +020063 RtpPayloadParams params(kSsrc2, &state2, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020064 EncodedImage encoded_image;
65 encoded_image.rotation_ = kVideoRotation_90;
66 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020067 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020068
69 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020070 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020071 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020072 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020073 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020074 codec_info.codecSpecific.VP8.nonReference = true;
75
philipelbf2b6202018-08-27 14:33:18 +020076 RTPVideoHeader header =
77 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
78
79 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020080 codec_info.codecSpecific.VP8.temporalIdx = 1;
81 codec_info.codecSpecific.VP8.layerSync = true;
82
83 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020084
85 EXPECT_EQ(kVideoRotation_90, header.rotation);
86 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
87 EXPECT_EQ(1, header.simulcastIdx);
88 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +000089 const auto& vp8_header =
90 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
91 EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
92 EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
93 EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
94 EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
95 EXPECT_TRUE(vp8_header.layerSync);
96 EXPECT_TRUE(vp8_header.nonReference);
Stefan Holmerf7044682018-07-17 10:16:41 +020097}
98
99TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
100 RtpPayloadState state;
101 state.picture_id = kPictureId;
102 state.tl0_pic_idx = kTl0PicIdx;
Erik Språngcbc0cba2020-04-18 14:36:59 +0200103 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +0200104
105 EncodedImage encoded_image;
106 encoded_image.rotation_ = kVideoRotation_90;
107 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200108 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +0200109 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200110 codec_info.codecType = kVideoCodecVP9;
111 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
112 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200113 codec_info.codecSpecific.VP9.temporal_idx = 2;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100114 codec_info.end_of_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200115
philipelbf2b6202018-08-27 14:33:18 +0200116 RTPVideoHeader header =
117 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200118
119 EXPECT_EQ(kVideoRotation_90, header.rotation);
120 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
121 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100122 EXPECT_FALSE(header.color_space);
philipel29d88462018-08-08 14:26:00 +0200123 const auto& vp9_header =
124 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
125 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
126 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
127 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200128 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200129 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200130 codec_info.codecSpecific.VP9.num_spatial_layers);
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100131 EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
Stefan Holmerf7044682018-07-17 10:16:41 +0200132
133 // Next spatial layer.
134 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100135 codec_info.end_of_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200136
Niels Möllerd3b8c632018-08-27 15:33:42 +0200137 encoded_image.SetSpatialIndex(1);
Johannes Krond0b69a82018-12-03 14:18:53 +0100138 ColorSpace color_space(
139 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
140 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
Danil Chapovalovb7698942019-02-05 11:32:19 +0100141 encoded_image.SetColorSpace(color_space);
philipelbf2b6202018-08-27 14:33:18 +0200142 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200143
144 EXPECT_EQ(kVideoRotation_90, header.rotation);
145 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
146 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100147 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
philipel29d88462018-08-08 14:26:00 +0200148 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
149 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
150 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200151 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200152 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200153 codec_info.codecSpecific.VP9.num_spatial_layers);
Danil Chapovalov06bbeb32020-11-11 12:42:56 +0100154 EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
Stefan Holmerf7044682018-07-17 10:16:41 +0200155}
156
Stefan Holmerf7044682018-07-17 10:16:41 +0200157TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
158 RtpPayloadState state;
159 state.picture_id = kInitialPictureId1;
160 state.tl0_pic_idx = kInitialTl0PicIdx1;
161
162 EncodedImage encoded_image;
163 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200164 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200165
Erik Språngcbc0cba2020-04-18 14:36:59 +0200166 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200167 RTPVideoHeader header =
168 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200169 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000170 EXPECT_EQ(kInitialPictureId1 + 1,
171 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200172
173 // State should hold latest used picture id and tl0_pic_idx.
174 state = params.state();
175 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
176 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
177}
178
179TEST(RtpPayloadParamsTest, PictureIdWraps) {
180 RtpPayloadState state;
181 state.picture_id = kMaxTwoBytePictureId;
182 state.tl0_pic_idx = kInitialTl0PicIdx1;
183
184 EncodedImage encoded_image;
185 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200186 codec_info.codecType = kVideoCodecVP8;
187 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
188
Erik Språngcbc0cba2020-04-18 14:36:59 +0200189 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200190 RTPVideoHeader header =
191 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200192 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000193 EXPECT_EQ(0,
194 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200195
196 // State should hold latest used picture id and tl0_pic_idx.
197 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
198 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
199}
200
Emil Lundmark6c81a422022-05-18 17:13:34 +0200201TEST(RtpPayloadParamsTest, CreatesGenericDescriptorForVp8) {
202 constexpr auto kSwitch = DecodeTargetIndication::kSwitch;
203 constexpr auto kNotPresent = DecodeTargetIndication::kNotPresent;
204
205 RtpPayloadState state;
206 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
207
208 EncodedImage key_frame_image;
209 key_frame_image._frameType = VideoFrameType::kVideoFrameKey;
210 CodecSpecificInfo key_frame_info;
211 key_frame_info.codecType = kVideoCodecVP8;
212 key_frame_info.codecSpecific.VP8.temporalIdx = 0;
213 RTPVideoHeader key_frame_header = params.GetRtpVideoHeader(
214 key_frame_image, &key_frame_info, /*shared_frame_id=*/123);
215
216 EncodedImage delta_t1_image;
217 delta_t1_image._frameType = VideoFrameType::kVideoFrameDelta;
218 CodecSpecificInfo delta_t1_info;
219 delta_t1_info.codecType = kVideoCodecVP8;
220 delta_t1_info.codecSpecific.VP8.temporalIdx = 1;
221 RTPVideoHeader delta_t1_header = params.GetRtpVideoHeader(
222 delta_t1_image, &delta_t1_info, /*shared_frame_id=*/124);
223
224 EncodedImage delta_t0_image;
225 delta_t0_image._frameType = VideoFrameType::kVideoFrameDelta;
226 CodecSpecificInfo delta_t0_info;
227 delta_t0_info.codecType = kVideoCodecVP8;
228 delta_t0_info.codecSpecific.VP8.temporalIdx = 0;
229 RTPVideoHeader delta_t0_header = params.GetRtpVideoHeader(
230 delta_t0_image, &delta_t0_info, /*shared_frame_id=*/125);
231
232 EXPECT_THAT(
233 key_frame_header,
234 AllOf(Field(&RTPVideoHeader::codec, kVideoCodecVP8),
235 Field(&RTPVideoHeader::frame_type, VideoFrameType::kVideoFrameKey),
236 Field(&RTPVideoHeader::generic,
237 Optional(AllOf(
238 Field(&GenericDescriptorInfo::frame_id, 123),
239 Field(&GenericDescriptorInfo::spatial_index, 0),
240 Field(&GenericDescriptorInfo::temporal_index, 0),
241 Field(&GenericDescriptorInfo::decode_target_indications,
242 ElementsAre(kSwitch, kSwitch, kSwitch, kSwitch)),
243 Field(&GenericDescriptorInfo::dependencies, IsEmpty()),
244 Field(&GenericDescriptorInfo::chain_diffs,
245 ElementsAre(0)))))));
246
247 EXPECT_THAT(
248 delta_t1_header,
249 AllOf(
250 Field(&RTPVideoHeader::codec, kVideoCodecVP8),
251 Field(&RTPVideoHeader::frame_type, VideoFrameType::kVideoFrameDelta),
252 Field(
253 &RTPVideoHeader::generic,
254 Optional(AllOf(
255 Field(&GenericDescriptorInfo::frame_id, 124),
256 Field(&GenericDescriptorInfo::spatial_index, 0),
257 Field(&GenericDescriptorInfo::temporal_index, 1),
258 Field(&GenericDescriptorInfo::decode_target_indications,
259 ElementsAre(kNotPresent, kSwitch, kSwitch, kSwitch)),
260 Field(&GenericDescriptorInfo::dependencies, ElementsAre(123)),
261 Field(&GenericDescriptorInfo::chain_diffs,
262 ElementsAre(1)))))));
263
264 EXPECT_THAT(
265 delta_t0_header,
266 AllOf(
267 Field(&RTPVideoHeader::codec, kVideoCodecVP8),
268 Field(&RTPVideoHeader::frame_type, VideoFrameType::kVideoFrameDelta),
269 Field(
270 &RTPVideoHeader::generic,
271 Optional(AllOf(
272 Field(&GenericDescriptorInfo::frame_id, 125),
273 Field(&GenericDescriptorInfo::spatial_index, 0),
274 Field(&GenericDescriptorInfo::temporal_index, 0),
275 Field(&GenericDescriptorInfo::decode_target_indications,
276 ElementsAre(kSwitch, kSwitch, kSwitch, kSwitch)),
277 Field(&GenericDescriptorInfo::dependencies, ElementsAre(123)),
278 Field(&GenericDescriptorInfo::chain_diffs,
279 ElementsAre(2)))))));
280}
281
Stefan Holmerf7044682018-07-17 10:16:41 +0200282TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
283 RtpPayloadState state;
284 state.picture_id = kInitialPictureId1;
285 state.tl0_pic_idx = kInitialTl0PicIdx1;
286
287 EncodedImage encoded_image;
288 // Modules are sending for this test.
289 // OnEncodedImage, temporalIdx: 1.
290 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200291 codec_info.codecType = kVideoCodecVP8;
292 codec_info.codecSpecific.VP8.temporalIdx = 1;
293
Erik Språngcbc0cba2020-04-18 14:36:59 +0200294 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200295 RTPVideoHeader header =
296 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200297
298 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000299 const auto& vp8_header =
300 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
301 EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
302 EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200303
304 // OnEncodedImage, temporalIdx: 0.
305 codec_info.codecSpecific.VP8.temporalIdx = 0;
306
philipelbf2b6202018-08-27 14:33:18 +0200307 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200308 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000309 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
310 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200311
312 // State should hold latest used picture id and tl0_pic_idx.
313 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
314 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
315}
316
317TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
318 RtpPayloadState state;
319 state.picture_id = kInitialPictureId1;
320 state.tl0_pic_idx = kInitialTl0PicIdx1;
321
322 EncodedImage encoded_image;
323 // Modules are sending for this test.
324 // OnEncodedImage, temporalIdx: 1.
325 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200326 codec_info.codecType = kVideoCodecVP9;
327 codec_info.codecSpecific.VP9.temporal_idx = 1;
328 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
329
Erik Språngcbc0cba2020-04-18 14:36:59 +0200330 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200331 RTPVideoHeader header =
332 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200333
334 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200335 const auto& vp9_header =
336 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
337 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
338 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200339
340 // OnEncodedImage, temporalIdx: 0.
341 codec_info.codecSpecific.VP9.temporal_idx = 0;
342
philipelbf2b6202018-08-27 14:33:18 +0200343 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200344
345 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200346 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
347 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200348
349 // OnEncodedImage, first_frame_in_picture = false
350 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
351
philipelbf2b6202018-08-27 14:33:18 +0200352 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200353
354 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200355 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
356 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200357
358 // State should hold latest used picture id and tl0_pic_idx.
359 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
360 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
361}
philipelbf2b6202018-08-27 14:33:18 +0200362
363TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100364 test::ScopedKeyValueConfig field_trials("WebRTC-GenericPictureId/Enabled/");
philipelbf2b6202018-08-27 14:33:18 +0200365 RtpPayloadState state{};
366
367 EncodedImage encoded_image;
philipeld1d03592019-03-01 13:53:55 +0100368 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200369 codec_info.codecType = kVideoCodecGeneric;
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100370 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
philipelbf2b6202018-08-27 14:33:18 +0200371
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100372 RtpPayloadParams params(kSsrc1, &state, field_trials);
philipelbf2b6202018-08-27 14:33:18 +0200373 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100374 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
philipelbf2b6202018-08-27 14:33:18 +0200375
376 EXPECT_EQ(kVideoCodecGeneric, header.codec);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100377 const auto* generic =
378 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
379 ASSERT_TRUE(generic);
380 EXPECT_EQ(0, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200381
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100382 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
383 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100384 generic =
385 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
386 ASSERT_TRUE(generic);
387 EXPECT_EQ(1, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200388}
389
philipel8aba8fe2019-06-13 15:13:16 +0200390TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
philipel5b231de2021-09-01 15:21:16 +0200391 RtpPayloadState state;
philipel8aba8fe2019-06-13 15:13:16 +0200392
393 EncodedImage encoded_image;
394 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
395 CodecSpecificInfo codec_info;
396 codec_info.codecType = kVideoCodecGeneric;
397
Erik Språngcbc0cba2020-04-18 14:36:59 +0200398 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipel8aba8fe2019-06-13 15:13:16 +0200399 RTPVideoHeader header =
400 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
401
philipel5b231de2021-09-01 15:21:16 +0200402 EXPECT_THAT(header.codec, Eq(kVideoCodecGeneric));
403
philipel8aba8fe2019-06-13 15:13:16 +0200404 ASSERT_TRUE(header.generic);
philipel5b231de2021-09-01 15:21:16 +0200405 EXPECT_THAT(header.generic->frame_id, Eq(0));
406 EXPECT_THAT(header.generic->spatial_index, Eq(0));
407 EXPECT_THAT(header.generic->temporal_index, Eq(0));
408 EXPECT_THAT(header.generic->decode_target_indications,
409 ElementsAre(DecodeTargetIndication::kSwitch));
philipel8aba8fe2019-06-13 15:13:16 +0200410 EXPECT_THAT(header.generic->dependencies, IsEmpty());
philipel5b231de2021-09-01 15:21:16 +0200411 EXPECT_THAT(header.generic->chain_diffs, ElementsAre(0));
philipel8aba8fe2019-06-13 15:13:16 +0200412
413 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipel5b231de2021-09-01 15:21:16 +0200414 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 3);
philipel8aba8fe2019-06-13 15:13:16 +0200415 ASSERT_TRUE(header.generic);
philipel5b231de2021-09-01 15:21:16 +0200416 EXPECT_THAT(header.generic->frame_id, Eq(3));
417 EXPECT_THAT(header.generic->spatial_index, Eq(0));
418 EXPECT_THAT(header.generic->temporal_index, Eq(0));
philipel8aba8fe2019-06-13 15:13:16 +0200419 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
philipel5b231de2021-09-01 15:21:16 +0200420 EXPECT_THAT(header.generic->decode_target_indications,
421 ElementsAre(DecodeTargetIndication::kSwitch));
422 EXPECT_THAT(header.generic->chain_diffs, ElementsAre(3));
philipel8aba8fe2019-06-13 15:13:16 +0200423}
424
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100425TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100426 RtpPayloadState state;
427 EncodedImage encoded_image;
428 CodecSpecificInfo codec_info;
429
Erik Språngcbc0cba2020-04-18 14:36:59 +0200430 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100431
432 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
433 codec_info.generic_frame_info =
434 GenericFrameInfo::Builder().S(1).T(0).Dtis("S").Build();
435 codec_info.generic_frame_info->encoder_buffers = {
436 {/*id=*/0, /*referenced=*/false, /*updated=*/true}};
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200437 codec_info.generic_frame_info->part_of_chain = {true, false};
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100438 RTPVideoHeader key_header =
439 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/1);
440
441 ASSERT_TRUE(key_header.generic);
442 EXPECT_EQ(key_header.generic->spatial_index, 1);
443 EXPECT_EQ(key_header.generic->temporal_index, 0);
444 EXPECT_EQ(key_header.generic->frame_id, 1);
445 EXPECT_THAT(key_header.generic->dependencies, IsEmpty());
446 EXPECT_THAT(key_header.generic->decode_target_indications,
447 ElementsAre(DecodeTargetIndication::kSwitch));
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200448 EXPECT_THAT(key_header.generic->chain_diffs, SizeIs(2));
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100449
450 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
451 codec_info.generic_frame_info =
452 GenericFrameInfo::Builder().S(2).T(3).Dtis("D").Build();
453 codec_info.generic_frame_info->encoder_buffers = {
454 {/*id=*/0, /*referenced=*/true, /*updated=*/false}};
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200455 codec_info.generic_frame_info->part_of_chain = {false, false};
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100456 RTPVideoHeader delta_header =
457 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/3);
458
459 ASSERT_TRUE(delta_header.generic);
460 EXPECT_EQ(delta_header.generic->spatial_index, 2);
461 EXPECT_EQ(delta_header.generic->temporal_index, 3);
462 EXPECT_EQ(delta_header.generic->frame_id, 3);
463 EXPECT_THAT(delta_header.generic->dependencies, ElementsAre(1));
464 EXPECT_THAT(delta_header.generic->decode_target_indications,
465 ElementsAre(DecodeTargetIndication::kDiscardable));
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200466 EXPECT_THAT(delta_header.generic->chain_diffs, SizeIs(2));
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100467}
468
philipelbf2b6202018-08-27 14:33:18 +0200469class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
470 public:
471 enum LayerSync { kNoSync, kSync };
472
philipel569397f2018-09-26 12:25:31 +0200473 RtpPayloadParamsVp8ToGenericTest()
Danil Chapovalov636865e2020-06-03 14:11:26 +0200474 : state_(), params_(123, &state_, trials_config_) {}
philipelbf2b6202018-08-27 14:33:18 +0200475
476 void ConvertAndCheck(int temporal_index,
477 int64_t shared_frame_id,
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000478 VideoFrameType frame_type,
philipelbf2b6202018-08-27 14:33:18 +0200479 LayerSync layer_sync,
philipelfab91292018-10-17 14:36:08 +0200480 const std::set<int64_t>& expected_deps,
481 uint16_t width = 0,
482 uint16_t height = 0) {
philipelbf2b6202018-08-27 14:33:18 +0200483 EncodedImage encoded_image;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000484 encoded_image._frameType = frame_type;
philipelfab91292018-10-17 14:36:08 +0200485 encoded_image._encodedWidth = width;
486 encoded_image._encodedHeight = height;
philipelbf2b6202018-08-27 14:33:18 +0200487
philipeld1d03592019-03-01 13:53:55 +0100488 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200489 codec_info.codecType = kVideoCodecVP8;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000490 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
491 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
philipelbf2b6202018-08-27 14:33:18 +0200492
493 RTPVideoHeader header =
494 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
495
496 ASSERT_TRUE(header.generic);
philipelbf2b6202018-08-27 14:33:18 +0200497 EXPECT_EQ(header.generic->spatial_index, 0);
498
499 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
500 EXPECT_EQ(header.generic->temporal_index, temporal_index);
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000501 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
502 header.generic->dependencies.end());
503 EXPECT_EQ(expected_deps, actual_deps);
philipelfab91292018-10-17 14:36:08 +0200504
505 EXPECT_EQ(header.width, width);
506 EXPECT_EQ(header.height, height);
philipelbf2b6202018-08-27 14:33:18 +0200507 }
508
509 protected:
Erik Språngcbc0cba2020-04-18 14:36:59 +0200510 FieldTrialBasedConfig trials_config_;
philipelbf2b6202018-08-27 14:33:18 +0200511 RtpPayloadState state_;
512 RtpPayloadParams params_;
513};
514
515TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000516 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
517 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
518 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200519}
520
521TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000522 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200523
524 EncodedImage encoded_image;
Niels Möller8f7ce222019-03-21 15:43:58 +0100525 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipeld1d03592019-03-01 13:53:55 +0100526 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200527 codec_info.codecType = kVideoCodecVP8;
528 codec_info.codecSpecific.VP8.temporalIdx =
529 RtpGenericFrameDescriptor::kMaxTemporalLayers;
530 codec_info.codecSpecific.VP8.layerSync = false;
531
532 RTPVideoHeader header =
533 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
534 EXPECT_FALSE(header.generic);
535}
536
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000537TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
538 // 02120212 pattern
539 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
540 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
541 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
542 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
philipelbf2b6202018-08-27 14:33:18 +0200543
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000544 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
545 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
546 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
547 {4}); // layer sync
548 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
philipelbf2b6202018-08-27 14:33:18 +0200549}
550
551TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
552 // 0101 pattern
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000553 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
554 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
philipelbf2b6202018-08-27 14:33:18 +0200555
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000556 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
557 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
philipelbf2b6202018-08-27 14:33:18 +0200558
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000559 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
560 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
philipelbf2b6202018-08-27 14:33:18 +0200561}
562
Emil Lundmarkb01e6452021-09-14 11:46:44 +0200563TEST(RtpPayloadParamsVp9ToGenericTest, NoScalability) {
564 RtpPayloadState state;
565 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
Danil Chapovalovaf366442021-04-22 15:20:28 +0200566
567 EncodedImage encoded_image;
568 CodecSpecificInfo codec_info;
569 codec_info.codecType = kVideoCodecVP9;
570 codec_info.codecSpecific.VP9.num_spatial_layers = 1;
571 codec_info.codecSpecific.VP9.temporal_idx = kNoTemporalIdx;
572 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
573 codec_info.end_of_picture = true;
574
575 // Key frame.
576 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
577 codec_info.codecSpecific.VP9.inter_pic_predicted = false;
578 codec_info.codecSpecific.VP9.num_ref_pics = 0;
579 RTPVideoHeader header = params.GetRtpVideoHeader(encoded_image, &codec_info,
580 /*shared_frame_id=*/1);
581
582 ASSERT_TRUE(header.generic);
583 EXPECT_EQ(header.generic->spatial_index, 0);
584 EXPECT_EQ(header.generic->temporal_index, 0);
585 EXPECT_EQ(header.generic->frame_id, 1);
586 ASSERT_THAT(header.generic->decode_target_indications, Not(IsEmpty()));
587 EXPECT_EQ(header.generic->decode_target_indications[0],
588 DecodeTargetIndication::kSwitch);
589 EXPECT_THAT(header.generic->dependencies, IsEmpty());
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200590 ASSERT_THAT(header.generic->chain_diffs, Not(IsEmpty()));
591 EXPECT_EQ(header.generic->chain_diffs[0], 0);
Danil Chapovalovaf366442021-04-22 15:20:28 +0200592
593 // Delta frame.
594 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
595 codec_info.codecSpecific.VP9.inter_pic_predicted = true;
596 codec_info.codecSpecific.VP9.num_ref_pics = 1;
597 codec_info.codecSpecific.VP9.p_diff[0] = 1;
598 header = params.GetRtpVideoHeader(encoded_image, &codec_info,
599 /*shared_frame_id=*/3);
600
601 ASSERT_TRUE(header.generic);
602 EXPECT_EQ(header.generic->spatial_index, 0);
603 EXPECT_EQ(header.generic->temporal_index, 0);
604 EXPECT_EQ(header.generic->frame_id, 3);
605 ASSERT_THAT(header.generic->decode_target_indications, Not(IsEmpty()));
606 EXPECT_EQ(header.generic->decode_target_indications[0],
607 DecodeTargetIndication::kSwitch);
608 EXPECT_THAT(header.generic->dependencies, ElementsAre(1));
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200609 ASSERT_THAT(header.generic->chain_diffs, Not(IsEmpty()));
Danil Chapovalovaf366442021-04-22 15:20:28 +0200610 // previous frame in the chain was frame#1,
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200611 EXPECT_EQ(header.generic->chain_diffs[0], 3 - 1);
Danil Chapovalovaf366442021-04-22 15:20:28 +0200612}
613
Emil Lundmarkb01e6452021-09-14 11:46:44 +0200614TEST(RtpPayloadParamsVp9ToGenericTest, TemporalScalabilityWith2Layers) {
Danil Chapovalovaf366442021-04-22 15:20:28 +0200615 // Test with 2 temporal layers structure that is not used by webrtc:
616 // 1---3 5
617 // / / / ...
618 // 0---2---4---
Emil Lundmarkb01e6452021-09-14 11:46:44 +0200619 RtpPayloadState state;
620 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
Danil Chapovalovaf366442021-04-22 15:20:28 +0200621
622 EncodedImage image;
623 CodecSpecificInfo info;
624 info.codecType = kVideoCodecVP9;
625 info.codecSpecific.VP9.num_spatial_layers = 1;
626 info.codecSpecific.VP9.first_frame_in_picture = true;
627 info.end_of_picture = true;
628
629 RTPVideoHeader headers[6];
630 // Key frame.
631 image._frameType = VideoFrameType::kVideoFrameKey;
632 info.codecSpecific.VP9.inter_pic_predicted = false;
633 info.codecSpecific.VP9.num_ref_pics = 0;
634 info.codecSpecific.VP9.temporal_up_switch = true;
635 info.codecSpecific.VP9.temporal_idx = 0;
636 headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
637
638 // Delta frames.
639 info.codecSpecific.VP9.inter_pic_predicted = true;
640 image._frameType = VideoFrameType::kVideoFrameDelta;
641
642 info.codecSpecific.VP9.temporal_up_switch = true;
643 info.codecSpecific.VP9.temporal_idx = 1;
644 info.codecSpecific.VP9.num_ref_pics = 1;
645 info.codecSpecific.VP9.p_diff[0] = 1;
646 headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
647
648 info.codecSpecific.VP9.temporal_up_switch = false;
649 info.codecSpecific.VP9.temporal_idx = 0;
650 info.codecSpecific.VP9.num_ref_pics = 1;
651 info.codecSpecific.VP9.p_diff[0] = 2;
652 headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
653
654 info.codecSpecific.VP9.temporal_up_switch = false;
655 info.codecSpecific.VP9.temporal_idx = 1;
656 info.codecSpecific.VP9.num_ref_pics = 2;
657 info.codecSpecific.VP9.p_diff[0] = 1;
658 info.codecSpecific.VP9.p_diff[1] = 2;
659 headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
660
661 info.codecSpecific.VP9.temporal_up_switch = true;
662 info.codecSpecific.VP9.temporal_idx = 0;
663 info.codecSpecific.VP9.num_ref_pics = 1;
664 info.codecSpecific.VP9.p_diff[0] = 2;
665 headers[4] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/9);
666
667 info.codecSpecific.VP9.temporal_up_switch = true;
668 info.codecSpecific.VP9.temporal_idx = 1;
669 info.codecSpecific.VP9.num_ref_pics = 1;
670 info.codecSpecific.VP9.p_diff[0] = 1;
671 headers[5] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/11);
672
673 ASSERT_TRUE(headers[0].generic);
674 int num_decode_targets = headers[0].generic->decode_target_indications.size();
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200675 int num_chains = headers[0].generic->chain_diffs.size();
Danil Chapovalovaf366442021-04-22 15:20:28 +0200676 ASSERT_GE(num_decode_targets, 2);
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200677 ASSERT_GE(num_chains, 1);
Danil Chapovalovaf366442021-04-22 15:20:28 +0200678
679 for (int frame_idx = 0; frame_idx < 6; ++frame_idx) {
680 const RTPVideoHeader& header = headers[frame_idx];
681 ASSERT_TRUE(header.generic);
682 EXPECT_EQ(header.generic->spatial_index, 0);
683 EXPECT_EQ(header.generic->temporal_index, frame_idx % 2);
684 EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
685 ASSERT_THAT(header.generic->decode_target_indications,
686 SizeIs(num_decode_targets));
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200687 ASSERT_THAT(header.generic->chain_diffs, SizeIs(num_chains));
Danil Chapovalovaf366442021-04-22 15:20:28 +0200688 // Expect only T0 frames are needed for the 1st decode target.
689 if (header.generic->temporal_index == 0) {
690 EXPECT_NE(header.generic->decode_target_indications[0],
691 DecodeTargetIndication::kNotPresent);
692 } else {
693 EXPECT_EQ(header.generic->decode_target_indications[0],
694 DecodeTargetIndication::kNotPresent);
695 }
696 // Expect all frames are needed for the 2nd decode target.
697 EXPECT_NE(header.generic->decode_target_indications[1],
698 DecodeTargetIndication::kNotPresent);
699 }
700
701 // Expect switch at every beginning of the pattern.
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200702 EXPECT_THAT(headers[0].generic->decode_target_indications[0],
703 DecodeTargetIndication::kSwitch);
704 EXPECT_THAT(headers[0].generic->decode_target_indications[1],
705 DecodeTargetIndication::kSwitch);
706 EXPECT_THAT(headers[4].generic->decode_target_indications[0],
707 DecodeTargetIndication::kSwitch);
708 EXPECT_THAT(headers[4].generic->decode_target_indications[1],
709 DecodeTargetIndication::kSwitch);
Danil Chapovalovaf366442021-04-22 15:20:28 +0200710
711 EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // T0, 1
712 EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // T1, 3
713 EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // T0, 5
714 EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(5, 3)); // T1, 7
715 EXPECT_THAT(headers[4].generic->dependencies, ElementsAre(5)); // T0, 9
716 EXPECT_THAT(headers[5].generic->dependencies, ElementsAre(9)); // T1, 11
717
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200718 EXPECT_THAT(headers[0].generic->chain_diffs[0], Eq(0));
719 EXPECT_THAT(headers[1].generic->chain_diffs[0], Eq(2));
720 EXPECT_THAT(headers[2].generic->chain_diffs[0], Eq(4));
721 EXPECT_THAT(headers[3].generic->chain_diffs[0], Eq(2));
722 EXPECT_THAT(headers[4].generic->chain_diffs[0], Eq(4));
723 EXPECT_THAT(headers[5].generic->chain_diffs[0], Eq(2));
Danil Chapovalovaf366442021-04-22 15:20:28 +0200724}
725
Emil Lundmarkb01e6452021-09-14 11:46:44 +0200726TEST(RtpPayloadParamsVp9ToGenericTest, TemporalScalabilityWith3Layers) {
Danil Chapovalovaf366442021-04-22 15:20:28 +0200727 // Test with 3 temporal layers structure that is not used by webrtc, but used
728 // by chromium: https://imgur.com/pURAGvp
Emil Lundmarkb01e6452021-09-14 11:46:44 +0200729 RtpPayloadState state;
730 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
Danil Chapovalovaf366442021-04-22 15:20:28 +0200731
732 EncodedImage image;
733 CodecSpecificInfo info;
734 info.codecType = kVideoCodecVP9;
735 info.codecSpecific.VP9.num_spatial_layers = 1;
736 info.codecSpecific.VP9.first_frame_in_picture = true;
737 info.end_of_picture = true;
738
739 RTPVideoHeader headers[9];
740 // Key frame.
741 image._frameType = VideoFrameType::kVideoFrameKey;
742 info.codecSpecific.VP9.inter_pic_predicted = false;
743 info.codecSpecific.VP9.num_ref_pics = 0;
744 info.codecSpecific.VP9.temporal_up_switch = true;
745 info.codecSpecific.VP9.temporal_idx = 0;
746 headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
747
748 // Delta frames.
749 info.codecSpecific.VP9.inter_pic_predicted = true;
750 image._frameType = VideoFrameType::kVideoFrameDelta;
751
752 info.codecSpecific.VP9.temporal_up_switch = true;
753 info.codecSpecific.VP9.temporal_idx = 2;
754 info.codecSpecific.VP9.num_ref_pics = 1;
755 info.codecSpecific.VP9.p_diff[0] = 1;
756 headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
757
758 info.codecSpecific.VP9.temporal_up_switch = true;
759 info.codecSpecific.VP9.temporal_idx = 1;
760 info.codecSpecific.VP9.num_ref_pics = 1;
761 info.codecSpecific.VP9.p_diff[0] = 2;
762 headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
763
764 info.codecSpecific.VP9.temporal_up_switch = true;
765 info.codecSpecific.VP9.temporal_idx = 2;
766 info.codecSpecific.VP9.num_ref_pics = 1;
767 info.codecSpecific.VP9.p_diff[0] = 1;
768 headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
769
770 info.codecSpecific.VP9.temporal_up_switch = false;
771 info.codecSpecific.VP9.temporal_idx = 0;
772 info.codecSpecific.VP9.num_ref_pics = 1;
773 info.codecSpecific.VP9.p_diff[0] = 4;
774 headers[4] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/9);
775
776 info.codecSpecific.VP9.temporal_up_switch = true;
777 info.codecSpecific.VP9.temporal_idx = 2;
778 info.codecSpecific.VP9.num_ref_pics = 2;
779 info.codecSpecific.VP9.p_diff[0] = 1;
780 info.codecSpecific.VP9.p_diff[1] = 3;
781 headers[5] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/11);
782
783 info.codecSpecific.VP9.temporal_up_switch = false;
784 info.codecSpecific.VP9.temporal_idx = 1;
785 info.codecSpecific.VP9.num_ref_pics = 2;
786 info.codecSpecific.VP9.p_diff[0] = 2;
787 info.codecSpecific.VP9.p_diff[1] = 4;
788 headers[6] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/13);
789
790 info.codecSpecific.VP9.temporal_up_switch = true;
791 info.codecSpecific.VP9.temporal_idx = 2;
792 info.codecSpecific.VP9.num_ref_pics = 1;
793 info.codecSpecific.VP9.p_diff[0] = 1;
794 headers[7] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/15);
795
796 info.codecSpecific.VP9.temporal_up_switch = true;
797 info.codecSpecific.VP9.temporal_idx = 0;
798 info.codecSpecific.VP9.num_ref_pics = 1;
799 info.codecSpecific.VP9.p_diff[0] = 4;
800 headers[8] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/17);
801
802 ASSERT_TRUE(headers[0].generic);
803 int num_decode_targets = headers[0].generic->decode_target_indications.size();
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200804 int num_chains = headers[0].generic->chain_diffs.size();
Danil Chapovalovaf366442021-04-22 15:20:28 +0200805 ASSERT_GE(num_decode_targets, 3);
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200806 ASSERT_GE(num_chains, 1);
Danil Chapovalovaf366442021-04-22 15:20:28 +0200807
808 for (int frame_idx = 0; frame_idx < 9; ++frame_idx) {
809 const RTPVideoHeader& header = headers[frame_idx];
810 ASSERT_TRUE(header.generic);
811 EXPECT_EQ(header.generic->spatial_index, 0);
812 EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
813 ASSERT_THAT(header.generic->decode_target_indications,
814 SizeIs(num_decode_targets));
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200815 ASSERT_THAT(header.generic->chain_diffs, SizeIs(num_chains));
Danil Chapovalovaf366442021-04-22 15:20:28 +0200816 // Expect only T0 frames are needed for the 1st decode target.
817 if (header.generic->temporal_index == 0) {
818 EXPECT_NE(header.generic->decode_target_indications[0],
819 DecodeTargetIndication::kNotPresent);
820 } else {
821 EXPECT_EQ(header.generic->decode_target_indications[0],
822 DecodeTargetIndication::kNotPresent);
823 }
824 // Expect only T0 and T1 frames are needed for the 2nd decode target.
825 if (header.generic->temporal_index <= 1) {
826 EXPECT_NE(header.generic->decode_target_indications[1],
827 DecodeTargetIndication::kNotPresent);
828 } else {
829 EXPECT_EQ(header.generic->decode_target_indications[1],
830 DecodeTargetIndication::kNotPresent);
831 }
832 // Expect all frames are needed for the 3rd decode target.
833 EXPECT_NE(header.generic->decode_target_indications[2],
834 DecodeTargetIndication::kNotPresent);
835 }
836
837 EXPECT_EQ(headers[0].generic->temporal_index, 0);
838 EXPECT_EQ(headers[1].generic->temporal_index, 2);
839 EXPECT_EQ(headers[2].generic->temporal_index, 1);
840 EXPECT_EQ(headers[3].generic->temporal_index, 2);
841 EXPECT_EQ(headers[4].generic->temporal_index, 0);
842 EXPECT_EQ(headers[5].generic->temporal_index, 2);
843 EXPECT_EQ(headers[6].generic->temporal_index, 1);
844 EXPECT_EQ(headers[7].generic->temporal_index, 2);
845 EXPECT_EQ(headers[8].generic->temporal_index, 0);
846
847 // Expect switch at every beginning of the pattern.
848 EXPECT_THAT(headers[0].generic->decode_target_indications,
849 Each(DecodeTargetIndication::kSwitch));
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200850 EXPECT_THAT(headers[8].generic->decode_target_indications[0],
851 DecodeTargetIndication::kSwitch);
852 EXPECT_THAT(headers[8].generic->decode_target_indications[1],
853 DecodeTargetIndication::kSwitch);
854 EXPECT_THAT(headers[8].generic->decode_target_indications[2],
855 DecodeTargetIndication::kSwitch);
Danil Chapovalovaf366442021-04-22 15:20:28 +0200856
857 EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // T0, 1
858 EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // T2, 3
859 EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // T1, 5
860 EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(5)); // T2, 7
861 EXPECT_THAT(headers[4].generic->dependencies, ElementsAre(1)); // T0, 9
862 EXPECT_THAT(headers[5].generic->dependencies, ElementsAre(9, 5)); // T2, 11
863 EXPECT_THAT(headers[6].generic->dependencies, ElementsAre(9, 5)); // T1, 13
864 EXPECT_THAT(headers[7].generic->dependencies, ElementsAre(13)); // T2, 15
865 EXPECT_THAT(headers[8].generic->dependencies, ElementsAre(9)); // T0, 17
866
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200867 EXPECT_THAT(headers[0].generic->chain_diffs[0], Eq(0));
868 EXPECT_THAT(headers[1].generic->chain_diffs[0], Eq(2));
869 EXPECT_THAT(headers[2].generic->chain_diffs[0], Eq(4));
870 EXPECT_THAT(headers[3].generic->chain_diffs[0], Eq(6));
871 EXPECT_THAT(headers[4].generic->chain_diffs[0], Eq(8));
872 EXPECT_THAT(headers[5].generic->chain_diffs[0], Eq(2));
873 EXPECT_THAT(headers[6].generic->chain_diffs[0], Eq(4));
874 EXPECT_THAT(headers[7].generic->chain_diffs[0], Eq(6));
875 EXPECT_THAT(headers[8].generic->chain_diffs[0], Eq(8));
Danil Chapovalovaf366442021-04-22 15:20:28 +0200876}
877
Emil Lundmarkb01e6452021-09-14 11:46:44 +0200878TEST(RtpPayloadParamsVp9ToGenericTest, SpatialScalabilityKSvc) {
Danil Chapovalovaf366442021-04-22 15:20:28 +0200879 // 1---3--
880 // | ...
881 // 0---2--
Emil Lundmarkb01e6452021-09-14 11:46:44 +0200882 RtpPayloadState state;
883 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
Danil Chapovalovaf366442021-04-22 15:20:28 +0200884
885 EncodedImage image;
886 CodecSpecificInfo info;
887 info.codecType = kVideoCodecVP9;
888 info.codecSpecific.VP9.num_spatial_layers = 2;
889 info.codecSpecific.VP9.first_frame_in_picture = true;
890
891 RTPVideoHeader headers[4];
892 // Key frame.
893 image._frameType = VideoFrameType::kVideoFrameKey;
894 image.SetSpatialIndex(0);
895 info.codecSpecific.VP9.inter_pic_predicted = false;
896 info.codecSpecific.VP9.inter_layer_predicted = false;
897 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = false;
898 info.codecSpecific.VP9.num_ref_pics = 0;
899 info.codecSpecific.VP9.first_frame_in_picture = true;
900 info.end_of_picture = false;
901 headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
902
903 image.SetSpatialIndex(1);
904 info.codecSpecific.VP9.inter_layer_predicted = true;
905 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
906 info.codecSpecific.VP9.first_frame_in_picture = false;
907 info.end_of_picture = true;
908 headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
909
910 // Delta frames.
911 info.codecSpecific.VP9.inter_pic_predicted = true;
912 image._frameType = VideoFrameType::kVideoFrameDelta;
913 info.codecSpecific.VP9.num_ref_pics = 1;
914 info.codecSpecific.VP9.p_diff[0] = 1;
915
916 image.SetSpatialIndex(0);
917 info.codecSpecific.VP9.inter_layer_predicted = false;
918 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
919 info.codecSpecific.VP9.first_frame_in_picture = true;
920 info.end_of_picture = false;
921 headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
922
923 image.SetSpatialIndex(1);
924 info.codecSpecific.VP9.inter_layer_predicted = false;
925 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
926 info.codecSpecific.VP9.first_frame_in_picture = false;
927 info.end_of_picture = true;
928 headers[3] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/7);
929
930 ASSERT_TRUE(headers[0].generic);
931 int num_decode_targets = headers[0].generic->decode_target_indications.size();
932 // Rely on implementation detail there are always kMaxTemporalStreams temporal
933 // layers assumed, in particular assume Decode Target#0 matches layer S0T0,
934 // and Decode Target#kMaxTemporalStreams matches layer S1T0.
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200935 ASSERT_GE(num_decode_targets, kMaxTemporalStreams * 2);
936 int num_chains = headers[0].generic->chain_diffs.size();
937 ASSERT_GE(num_chains, 2);
Danil Chapovalovaf366442021-04-22 15:20:28 +0200938
939 for (int frame_idx = 0; frame_idx < 4; ++frame_idx) {
940 const RTPVideoHeader& header = headers[frame_idx];
941 ASSERT_TRUE(header.generic);
942 EXPECT_EQ(header.generic->spatial_index, frame_idx % 2);
943 EXPECT_EQ(header.generic->temporal_index, 0);
944 EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
945 ASSERT_THAT(header.generic->decode_target_indications,
946 SizeIs(num_decode_targets));
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200947 ASSERT_THAT(header.generic->chain_diffs, SizeIs(num_chains));
Danil Chapovalovaf366442021-04-22 15:20:28 +0200948 }
949
950 // Expect S0 key frame is switch for both Decode Targets.
951 EXPECT_EQ(headers[0].generic->decode_target_indications[0],
952 DecodeTargetIndication::kSwitch);
953 EXPECT_EQ(headers[0].generic->decode_target_indications[kMaxTemporalStreams],
954 DecodeTargetIndication::kSwitch);
955 // S1 key frame is only needed for the 2nd Decode Targets.
956 EXPECT_EQ(headers[1].generic->decode_target_indications[0],
957 DecodeTargetIndication::kNotPresent);
958 EXPECT_NE(headers[1].generic->decode_target_indications[kMaxTemporalStreams],
959 DecodeTargetIndication::kNotPresent);
960 // Delta frames are only needed for their own Decode Targets.
961 EXPECT_NE(headers[2].generic->decode_target_indications[0],
962 DecodeTargetIndication::kNotPresent);
963 EXPECT_EQ(headers[2].generic->decode_target_indications[kMaxTemporalStreams],
964 DecodeTargetIndication::kNotPresent);
965 EXPECT_EQ(headers[3].generic->decode_target_indications[0],
966 DecodeTargetIndication::kNotPresent);
967 EXPECT_NE(headers[3].generic->decode_target_indications[kMaxTemporalStreams],
968 DecodeTargetIndication::kNotPresent);
969
970 EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // S0, 1
971 EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // S1, 3
972 EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(1)); // S0, 5
973 EXPECT_THAT(headers[3].generic->dependencies, ElementsAre(3)); // S1, 7
974
Danil Chapovalov5b298ab2022-06-08 11:18:51 +0200975 EXPECT_THAT(headers[0].generic->chain_diffs[0], Eq(0));
976 EXPECT_THAT(headers[0].generic->chain_diffs[1], Eq(0));
977 EXPECT_THAT(headers[1].generic->chain_diffs[0], Eq(2));
978 EXPECT_THAT(headers[1].generic->chain_diffs[1], Eq(2));
979 EXPECT_THAT(headers[2].generic->chain_diffs[0], Eq(4));
980 EXPECT_THAT(headers[2].generic->chain_diffs[1], Eq(2));
981 EXPECT_THAT(headers[3].generic->chain_diffs[0], Eq(2));
982 EXPECT_THAT(headers[3].generic->chain_diffs[1], Eq(4));
983}
984
985TEST(RtpPayloadParamsVp9ToGenericTest,
986 IncreaseNumberOfSpatialLayersOnDeltaFrame) {
987 // S1 5--
988 // | ...
989 // S0 1---3--
990 RtpPayloadState state;
991 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
992
993 EncodedImage image;
994 CodecSpecificInfo info;
995 info.codecType = kVideoCodecVP9;
996 info.codecSpecific.VP9.num_spatial_layers = 1;
997 info.codecSpecific.VP9.first_frame_in_picture = true;
998
999 RTPVideoHeader headers[3];
1000 // Key frame.
1001 image._frameType = VideoFrameType::kVideoFrameKey;
1002 image.SetSpatialIndex(0);
1003 info.codecSpecific.VP9.inter_pic_predicted = false;
1004 info.codecSpecific.VP9.inter_layer_predicted = false;
1005 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
1006 info.codecSpecific.VP9.num_ref_pics = 0;
1007 info.codecSpecific.VP9.first_frame_in_picture = true;
1008 info.end_of_picture = true;
1009 headers[0] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/1);
1010
1011 // S0 delta frame.
1012 image._frameType = VideoFrameType::kVideoFrameDelta;
1013 info.codecSpecific.VP9.num_spatial_layers = 2;
1014 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = false;
1015 info.codecSpecific.VP9.first_frame_in_picture = true;
1016 info.codecSpecific.VP9.inter_pic_predicted = true;
1017 info.codecSpecific.VP9.num_ref_pics = 1;
1018 info.codecSpecific.VP9.p_diff[0] = 1;
1019 info.end_of_picture = false;
1020 headers[1] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/3);
1021
1022 // S1 delta frame.
1023 image.SetSpatialIndex(1);
1024 info.codecSpecific.VP9.inter_layer_predicted = true;
1025 info.codecSpecific.VP9.non_ref_for_inter_layer_pred = true;
1026 info.codecSpecific.VP9.first_frame_in_picture = false;
1027 info.codecSpecific.VP9.inter_pic_predicted = false;
1028 info.end_of_picture = true;
1029 headers[2] = params.GetRtpVideoHeader(image, &info, /*shared_frame_id=*/5);
1030
1031 ASSERT_TRUE(headers[0].generic);
1032 int num_decode_targets = headers[0].generic->decode_target_indications.size();
1033 int num_chains = headers[0].generic->chain_diffs.size();
1034 // Rely on implementation detail there are always kMaxTemporalStreams temporal
1035 // layers. In particular assume Decode Target#0 matches layer S0T0, and
1036 // Decode Target#kMaxTemporalStreams matches layer S1T0.
1037 static constexpr int kS0T0 = 0;
1038 static constexpr int kS1T0 = kMaxTemporalStreams;
1039 ASSERT_GE(num_decode_targets, 2);
1040 ASSERT_GE(num_chains, 2);
1041
1042 for (int frame_idx = 0; frame_idx < 3; ++frame_idx) {
1043 const RTPVideoHeader& header = headers[frame_idx];
1044 ASSERT_TRUE(header.generic);
1045 EXPECT_EQ(header.generic->temporal_index, 0);
1046 EXPECT_EQ(header.generic->frame_id, 1 + 2 * frame_idx);
1047 ASSERT_THAT(header.generic->decode_target_indications,
1048 SizeIs(num_decode_targets));
1049 ASSERT_THAT(header.generic->chain_diffs, SizeIs(num_chains));
1050 }
1051
1052 EXPECT_TRUE(headers[0].generic->active_decode_targets[kS0T0]);
1053 EXPECT_FALSE(headers[0].generic->active_decode_targets[kS1T0]);
1054
1055 EXPECT_TRUE(headers[1].generic->active_decode_targets[kS0T0]);
1056 EXPECT_TRUE(headers[1].generic->active_decode_targets[kS1T0]);
1057
1058 EXPECT_TRUE(headers[2].generic->active_decode_targets[kS0T0]);
1059 EXPECT_TRUE(headers[2].generic->active_decode_targets[kS1T0]);
1060
1061 EXPECT_EQ(headers[0].generic->decode_target_indications[kS0T0],
1062 DecodeTargetIndication::kSwitch);
1063
1064 EXPECT_EQ(headers[1].generic->decode_target_indications[kS0T0],
1065 DecodeTargetIndication::kSwitch);
1066
1067 EXPECT_EQ(headers[2].generic->decode_target_indications[kS0T0],
1068 DecodeTargetIndication::kNotPresent);
1069 EXPECT_EQ(headers[2].generic->decode_target_indications[kS1T0],
1070 DecodeTargetIndication::kSwitch);
1071
1072 EXPECT_THAT(headers[0].generic->dependencies, IsEmpty()); // S0, 1
1073 EXPECT_THAT(headers[1].generic->dependencies, ElementsAre(1)); // S0, 3
1074 EXPECT_THAT(headers[2].generic->dependencies, ElementsAre(3)); // S1, 5
1075
1076 EXPECT_EQ(headers[0].generic->chain_diffs[0], 0);
1077
1078 EXPECT_EQ(headers[1].generic->chain_diffs[0], 2);
1079 EXPECT_EQ(headers[1].generic->chain_diffs[1], 0);
1080
1081 EXPECT_EQ(headers[2].generic->chain_diffs[0], 2);
1082 EXPECT_EQ(headers[2].generic->chain_diffs[1], 2);
Danil Chapovalovaf366442021-04-22 15:20:28 +02001083}
1084
philipel8aba8fe2019-06-13 15:13:16 +02001085class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
1086 public:
1087 enum LayerSync { kNoSync, kSync };
1088
1089 RtpPayloadParamsH264ToGenericTest()
Danil Chapovalov636865e2020-06-03 14:11:26 +02001090 : state_(), params_(123, &state_, trials_config_) {}
philipel8aba8fe2019-06-13 15:13:16 +02001091
1092 void ConvertAndCheck(int temporal_index,
1093 int64_t shared_frame_id,
1094 VideoFrameType frame_type,
1095 LayerSync layer_sync,
1096 const std::set<int64_t>& expected_deps,
1097 uint16_t width = 0,
1098 uint16_t height = 0) {
1099 EncodedImage encoded_image;
1100 encoded_image._frameType = frame_type;
1101 encoded_image._encodedWidth = width;
1102 encoded_image._encodedHeight = height;
1103
1104 CodecSpecificInfo codec_info;
1105 codec_info.codecType = kVideoCodecH264;
1106 codec_info.codecSpecific.H264.temporal_idx = temporal_index;
1107 codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
1108
1109 RTPVideoHeader header =
1110 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
1111
1112 ASSERT_TRUE(header.generic);
philipel8aba8fe2019-06-13 15:13:16 +02001113 EXPECT_EQ(header.generic->spatial_index, 0);
1114
1115 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
1116 EXPECT_EQ(header.generic->temporal_index, temporal_index);
1117 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
1118 header.generic->dependencies.end());
1119 EXPECT_EQ(expected_deps, actual_deps);
1120
1121 EXPECT_EQ(header.width, width);
1122 EXPECT_EQ(header.height, height);
1123 }
1124
1125 protected:
Erik Språngcbc0cba2020-04-18 14:36:59 +02001126 FieldTrialBasedConfig trials_config_;
philipel8aba8fe2019-06-13 15:13:16 +02001127 RtpPayloadState state_;
1128 RtpPayloadParams params_;
1129};
1130
1131TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
1132 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
1133 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
1134 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
1135}
1136
1137TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
1138 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
1139
1140 EncodedImage encoded_image;
1141 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
1142 CodecSpecificInfo codec_info;
1143 codec_info.codecType = kVideoCodecH264;
1144 codec_info.codecSpecific.H264.temporal_idx =
1145 RtpGenericFrameDescriptor::kMaxTemporalLayers;
1146 codec_info.codecSpecific.H264.base_layer_sync = false;
1147
1148 RTPVideoHeader header =
1149 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
1150 EXPECT_FALSE(header.generic);
1151}
1152
1153TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
1154 // 02120212 pattern
1155 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
1156 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
1157 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
1158 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
1159
1160 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
1161 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
1162 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
1163 {4}); // layer sync
1164 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
1165}
1166
1167TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
1168 // 0101 pattern
1169 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
1170 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
1171
1172 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
1173 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
1174
1175 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
1176 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
1177}
1178
Emil Lundmark6c81a422022-05-18 17:13:34 +02001179} // namespace
Stefan Holmerf7044682018-07-17 10:16:41 +02001180} // namespace webrtc