1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "call/rtp_payload_params.h"
12
13 #include <string.h>
14
15 #include <map>
16 #include <set>
17
18 #include "absl/container/inlined_vector.h"
19 #include "absl/types/optional.h"
20 #include "absl/types/variant.h"
21 #include "api/transport/field_trial_based_config.h"
22 #include "api/video/video_content_type.h"
23 #include "api/video/video_rotation.h"
24 #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"
28 #include "modules/video_coding/include/video_codec_interface.h"
29 #include "test/explicit_key_value_config.h"
30 #include "test/gmock.h"
31 #include "test/gtest.h"
32 #include "test/scoped_key_value_config.h"
33
34 namespace webrtc {
35 namespace {
36
37 using ::testing::AllOf;
38 using ::testing::Each;
39 using ::testing::ElementsAre;
40 using ::testing::Eq;
41 using ::testing::Field;
42 using ::testing::IsEmpty;
43 using ::testing::Optional;
44 using ::testing::SizeIs;
45
46 using GenericDescriptorInfo = RTPVideoHeader::GenericDescriptorInfo;
47
48 const uint32_t kSsrc1 = 12345;
49 const uint32_t kSsrc2 = 23456;
50 const int16_t kPictureId = 123;
51 const int16_t kTl0PicIdx = 20;
52 const uint8_t kTemporalIdx = 1;
53 const int16_t kInitialPictureId1 = 222;
54 const int16_t kInitialTl0PicIdx1 = 99;
55 const int64_t kDontCare = 0;
56
TEST(RtpPayloadParamsTest,InfoMappedToRtpVideoHeader_Vp8)57 TEST(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
63 RtpPayloadParams params(kSsrc2, &state2, FieldTrialBasedConfig());
64 EncodedImage encoded_image;
65 encoded_image.rotation_ = kVideoRotation_90;
66 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
67 encoded_image.SetSpatialIndex(1);
68
69 CodecSpecificInfo codec_info;
70 codec_info.codecType = kVideoCodecVP8;
71 codec_info.codecSpecific.VP8.temporalIdx = 0;
72 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
73 codec_info.codecSpecific.VP8.layerSync = false;
74 codec_info.codecSpecific.VP8.nonReference = true;
75
76 RTPVideoHeader header =
77 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
78
79 codec_info.codecType = kVideoCodecVP8;
80 codec_info.codecSpecific.VP8.temporalIdx = 1;
81 codec_info.codecSpecific.VP8.layerSync = true;
82
83 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
84
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);
89 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);
97 }
98
TEST(RtpPayloadParamsTest,InfoMappedToRtpVideoHeader_Vp9)99 TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
100 RtpPayloadState state;
101 state.picture_id = kPictureId;
102 state.tl0_pic_idx = kTl0PicIdx;
103 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
104
105 EncodedImage encoded_image;
106 encoded_image.rotation_ = kVideoRotation_90;
107 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
108 encoded_image.SetSpatialIndex(0);
109 CodecSpecificInfo codec_info;
110 codec_info.codecType = kVideoCodecVP9;
111 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
112 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
113 codec_info.codecSpecific.VP9.temporal_idx = 2;
114 codec_info.end_of_picture = false;
115
116 RTPVideoHeader header =
117 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
118
119 EXPECT_EQ(kVideoRotation_90, header.rotation);
120 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
121 EXPECT_EQ(kVideoCodecVP9, header.codec);
122 EXPECT_FALSE(header.color_space);
123 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);
128 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
129 EXPECT_EQ(vp9_header.num_spatial_layers,
130 codec_info.codecSpecific.VP9.num_spatial_layers);
131 EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
132
133 // Next spatial layer.
134 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
135 codec_info.end_of_picture = true;
136
137 encoded_image.SetSpatialIndex(1);
138 ColorSpace color_space(
139 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
140 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
141 encoded_image.SetColorSpace(color_space);
142 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
143
144 EXPECT_EQ(kVideoRotation_90, header.rotation);
145 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
146 EXPECT_EQ(kVideoCodecVP9, header.codec);
147 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
148 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);
151 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
152 EXPECT_EQ(vp9_header.num_spatial_layers,
153 codec_info.codecSpecific.VP9.num_spatial_layers);
154 EXPECT_EQ(vp9_header.end_of_picture, codec_info.end_of_picture);
155 }
156
TEST(RtpPayloadParamsTest,PictureIdIsSetForVp8)157 TEST(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;
164 codec_info.codecType = kVideoCodecVP8;
165
166 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
167 RTPVideoHeader header =
168 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
169 EXPECT_EQ(kVideoCodecVP8, header.codec);
170 EXPECT_EQ(kInitialPictureId1 + 1,
171 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
172
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
TEST(RtpPayloadParamsTest,PictureIdWraps)179 TEST(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;
186 codec_info.codecType = kVideoCodecVP8;
187 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
188
189 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
190 RTPVideoHeader header =
191 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
192 EXPECT_EQ(kVideoCodecVP8, header.codec);
193 EXPECT_EQ(0,
194 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
195
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
TEST(RtpPayloadParamsTest,CreatesGenericDescriptorForVp8)201 TEST(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
TEST(RtpPayloadParamsTest,Tl0PicIdxUpdatedForVp8)282 TEST(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;
291 codec_info.codecType = kVideoCodecVP8;
292 codec_info.codecSpecific.VP8.temporalIdx = 1;
293
294 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
295 RTPVideoHeader header =
296 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
297
298 EXPECT_EQ(kVideoCodecVP8, header.codec);
299 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);
303
304 // OnEncodedImage, temporalIdx: 0.
305 codec_info.codecSpecific.VP8.temporalIdx = 0;
306
307 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
308 EXPECT_EQ(kVideoCodecVP8, header.codec);
309 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
310 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
311
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
TEST(RtpPayloadParamsTest,Tl0PicIdxUpdatedForVp9)317 TEST(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;
326 codec_info.codecType = kVideoCodecVP9;
327 codec_info.codecSpecific.VP9.temporal_idx = 1;
328 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
329
330 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
331 RTPVideoHeader header =
332 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
333
334 EXPECT_EQ(kVideoCodecVP9, header.codec);
335 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);
339
340 // OnEncodedImage, temporalIdx: 0.
341 codec_info.codecSpecific.VP9.temporal_idx = 0;
342
343 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
344
345 EXPECT_EQ(kVideoCodecVP9, header.codec);
346 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
347 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
348
349 // OnEncodedImage, first_frame_in_picture = false
350 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
351
352 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
353
354 EXPECT_EQ(kVideoCodecVP9, header.codec);
355 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
356 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
357
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 }
362
TEST(RtpPayloadParamsTest,PictureIdForOldGenericFormat)363 TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
364 test::ScopedKeyValueConfig field_trials("WebRTC-GenericPictureId/Enabled/");
365 RtpPayloadState state{};
366
367 EncodedImage encoded_image;
368 CodecSpecificInfo codec_info;
369 codec_info.codecType = kVideoCodecGeneric;
370 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
371
372 RtpPayloadParams params(kSsrc1, &state, field_trials);
373 RTPVideoHeader header =
374 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
375
376 EXPECT_EQ(kVideoCodecGeneric, header.codec);
377 const auto* generic =
378 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
379 ASSERT_TRUE(generic);
380 EXPECT_EQ(0, generic->picture_id);
381
382 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
383 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
384 generic =
385 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
386 ASSERT_TRUE(generic);
387 EXPECT_EQ(1, generic->picture_id);
388 }
389
TEST(RtpPayloadParamsTest,GenericDescriptorForGenericCodec)390 TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
391 RtpPayloadState state;
392
393 EncodedImage encoded_image;
394 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
395 CodecSpecificInfo codec_info;
396 codec_info.codecType = kVideoCodecGeneric;
397
398 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
399 RTPVideoHeader header =
400 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
401
402 EXPECT_THAT(header.codec, Eq(kVideoCodecGeneric));
403
404 ASSERT_TRUE(header.generic);
405 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));
410 EXPECT_THAT(header.generic->dependencies, IsEmpty());
411 EXPECT_THAT(header.generic->chain_diffs, ElementsAre(0));
412
413 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
414 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 3);
415 ASSERT_TRUE(header.generic);
416 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));
419 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
420 EXPECT_THAT(header.generic->decode_target_indications,
421 ElementsAre(DecodeTargetIndication::kSwitch));
422 EXPECT_THAT(header.generic->chain_diffs, ElementsAre(3));
423 }
424
TEST(RtpPayloadParamsTest,SetsGenericFromGenericFrameInfo)425 TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
426 RtpPayloadState state;
427 EncodedImage encoded_image;
428 CodecSpecificInfo codec_info;
429
430 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
431
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}};
437 codec_info.generic_frame_info->part_of_chain = {true, false};
438 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));
448 EXPECT_THAT(key_header.generic->chain_diffs, SizeIs(2));
449
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}};
455 codec_info.generic_frame_info->part_of_chain = {false, false};
456 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));
466 EXPECT_THAT(delta_header.generic->chain_diffs, SizeIs(2));
467 }
468
469 class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
470 public:
471 enum LayerSync { kNoSync, kSync };
472
RtpPayloadParamsVp8ToGenericTest()473 RtpPayloadParamsVp8ToGenericTest()
474 : state_(), params_(123, &state_, trials_config_) {}
475
ConvertAndCheck(int temporal_index,int64_t shared_frame_id,VideoFrameType frame_type,LayerSync layer_sync,const std::set<int64_t> & expected_deps,uint16_t width=0,uint16_t height=0)476 void ConvertAndCheck(int temporal_index,
477 int64_t shared_frame_id,
478 VideoFrameType frame_type,
479 LayerSync layer_sync,
480 const std::set<int64_t>& expected_deps,
481 uint16_t width = 0,
482 uint16_t height = 0) {
483 EncodedImage encoded_image;
484 encoded_image._frameType = frame_type;
485 encoded_image._encodedWidth = width;
486 encoded_image._encodedHeight = height;
487
488 CodecSpecificInfo codec_info;
489 codec_info.codecType = kVideoCodecVP8;
490 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
491 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
492
493 RTPVideoHeader header =
494 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
495
496 ASSERT_TRUE(header.generic);
497 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);
501 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
502 header.generic->dependencies.end());
503 EXPECT_EQ(expected_deps, actual_deps);
504
505 EXPECT_EQ(header.width, width);
506 EXPECT_EQ(header.height, height);
507 }
508
509 protected:
510 FieldTrialBasedConfig trials_config_;
511 RtpPayloadState state_;
512 RtpPayloadParams params_;
513 };
514
TEST_F(RtpPayloadParamsVp8ToGenericTest,Keyframe)515 TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
516 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);
519 }
520
TEST_F(RtpPayloadParamsVp8ToGenericTest,TooHighTemporalIndex)521 TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
522 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
523
524 EncodedImage encoded_image;
525 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
526 CodecSpecificInfo codec_info;
527 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
TEST_F(RtpPayloadParamsVp8ToGenericTest,LayerSync)537 TEST_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});
543
544 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});
549 }
550
TEST_F(RtpPayloadParamsVp8ToGenericTest,FrameIdGaps)551 TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
552 // 0101 pattern
553 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
554 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
555
556 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
557 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
558
559 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
560 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
561 }
562
TEST(RtpPayloadParamsVp9ToGenericTest,NoScalability)563 TEST(RtpPayloadParamsVp9ToGenericTest, NoScalability) {
564 RtpPayloadState state;
565 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
566
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());
590 ASSERT_THAT(header.generic->chain_diffs, Not(IsEmpty()));
591 EXPECT_EQ(header.generic->chain_diffs[0], 0);
592
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));
609 ASSERT_THAT(header.generic->chain_diffs, Not(IsEmpty()));
610 // previous frame in the chain was frame#1,
611 EXPECT_EQ(header.generic->chain_diffs[0], 3 - 1);
612 }
613
TEST(RtpPayloadParamsVp9ToGenericTest,TemporalScalabilityWith2Layers)614 TEST(RtpPayloadParamsVp9ToGenericTest, TemporalScalabilityWith2Layers) {
615 // Test with 2 temporal layers structure that is not used by webrtc:
616 // 1---3 5
617 // / / / ...
618 // 0---2---4---
619 RtpPayloadState state;
620 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
621
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();
675 int num_chains = headers[0].generic->chain_diffs.size();
676 ASSERT_GE(num_decode_targets, 2);
677 ASSERT_GE(num_chains, 1);
678
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));
687 ASSERT_THAT(header.generic->chain_diffs, SizeIs(num_chains));
688 // 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.
702 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);
710
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
718 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));
724 }
725
TEST(RtpPayloadParamsVp9ToGenericTest,TemporalScalabilityWith3Layers)726 TEST(RtpPayloadParamsVp9ToGenericTest, TemporalScalabilityWith3Layers) {
727 // Test with 3 temporal layers structure that is not used by webrtc, but used
728 // by chromium: https://imgur.com/pURAGvp
729 RtpPayloadState state;
730 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
731
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();
804 int num_chains = headers[0].generic->chain_diffs.size();
805 ASSERT_GE(num_decode_targets, 3);
806 ASSERT_GE(num_chains, 1);
807
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));
815 ASSERT_THAT(header.generic->chain_diffs, SizeIs(num_chains));
816 // 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));
850 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);
856
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
867 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));
876 }
877
TEST(RtpPayloadParamsVp9ToGenericTest,SpatialScalabilityKSvc)878 TEST(RtpPayloadParamsVp9ToGenericTest, SpatialScalabilityKSvc) {
879 // 1---3--
880 // | ...
881 // 0---2--
882 RtpPayloadState state;
883 RtpPayloadParams params(/*ssrc=*/123, &state, FieldTrialBasedConfig());
884
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.
935 ASSERT_GE(num_decode_targets, kMaxTemporalStreams * 2);
936 int num_chains = headers[0].generic->chain_diffs.size();
937 ASSERT_GE(num_chains, 2);
938
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));
947 ASSERT_THAT(header.generic->chain_diffs, SizeIs(num_chains));
948 }
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
975 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
TEST(RtpPayloadParamsVp9ToGenericTest,IncreaseNumberOfSpatialLayersOnDeltaFrame)985 TEST(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);
1083 }
1084
1085 class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
1086 public:
1087 enum LayerSync { kNoSync, kSync };
1088
RtpPayloadParamsH264ToGenericTest()1089 RtpPayloadParamsH264ToGenericTest()
1090 : state_(), params_(123, &state_, trials_config_) {}
1091
ConvertAndCheck(int temporal_index,int64_t shared_frame_id,VideoFrameType frame_type,LayerSync layer_sync,const std::set<int64_t> & expected_deps,uint16_t width=0,uint16_t height=0)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);
1113 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:
1126 FieldTrialBasedConfig trials_config_;
1127 RtpPayloadState state_;
1128 RtpPayloadParams params_;
1129 };
1130
TEST_F(RtpPayloadParamsH264ToGenericTest,Keyframe)1131 TEST_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
TEST_F(RtpPayloadParamsH264ToGenericTest,TooHighTemporalIndex)1137 TEST_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
TEST_F(RtpPayloadParamsH264ToGenericTest,LayerSync)1153 TEST_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
TEST_F(RtpPayloadParamsH264ToGenericTest,FrameIdGaps)1167 TEST_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
1179 } // namespace
1180 } // namespace webrtc
1181