• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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