• 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/field_trial.h"
30 #include "test/gmock.h"
31 #include "test/gtest.h"
32 
33 using ::testing::ElementsAre;
34 using ::testing::IsEmpty;
35 using ::testing::SizeIs;
36 
37 namespace webrtc {
38 namespace {
39 const uint32_t kSsrc1 = 12345;
40 const uint32_t kSsrc2 = 23456;
41 const int16_t kPictureId = 123;
42 const int16_t kTl0PicIdx = 20;
43 const uint8_t kTemporalIdx = 1;
44 const int16_t kInitialPictureId1 = 222;
45 const int16_t kInitialTl0PicIdx1 = 99;
46 const int64_t kDontCare = 0;
47 }  // namespace
48 
TEST(RtpPayloadParamsTest,InfoMappedToRtpVideoHeader_Vp8)49 TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
50   RtpPayloadState state2;
51   state2.picture_id = kPictureId;
52   state2.tl0_pic_idx = kTl0PicIdx;
53   std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
54 
55   RtpPayloadParams params(kSsrc2, &state2, FieldTrialBasedConfig());
56   EncodedImage encoded_image;
57   encoded_image.rotation_ = kVideoRotation_90;
58   encoded_image.content_type_ = VideoContentType::SCREENSHARE;
59   encoded_image.SetSpatialIndex(1);
60 
61   CodecSpecificInfo codec_info;
62   codec_info.codecType = kVideoCodecVP8;
63   codec_info.codecSpecific.VP8.temporalIdx = 0;
64   codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
65   codec_info.codecSpecific.VP8.layerSync = false;
66   codec_info.codecSpecific.VP8.nonReference = true;
67 
68   RTPVideoHeader header =
69       params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
70 
71   codec_info.codecType = kVideoCodecVP8;
72   codec_info.codecSpecific.VP8.temporalIdx = 1;
73   codec_info.codecSpecific.VP8.layerSync = true;
74 
75   header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
76 
77   EXPECT_EQ(kVideoRotation_90, header.rotation);
78   EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
79   EXPECT_EQ(1, header.simulcastIdx);
80   EXPECT_EQ(kVideoCodecVP8, header.codec);
81   const auto& vp8_header =
82       absl::get<RTPVideoHeaderVP8>(header.video_type_header);
83   EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
84   EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
85   EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
86   EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
87   EXPECT_TRUE(vp8_header.layerSync);
88   EXPECT_TRUE(vp8_header.nonReference);
89 }
90 
TEST(RtpPayloadParamsTest,InfoMappedToRtpVideoHeader_Vp9)91 TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
92   RtpPayloadState state;
93   state.picture_id = kPictureId;
94   state.tl0_pic_idx = kTl0PicIdx;
95   RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
96 
97   EncodedImage encoded_image;
98   encoded_image.rotation_ = kVideoRotation_90;
99   encoded_image.content_type_ = VideoContentType::SCREENSHARE;
100   encoded_image.SetSpatialIndex(0);
101   CodecSpecificInfo codec_info;
102   codec_info.codecType = kVideoCodecVP9;
103   codec_info.codecSpecific.VP9.num_spatial_layers = 3;
104   codec_info.codecSpecific.VP9.first_frame_in_picture = true;
105   codec_info.codecSpecific.VP9.temporal_idx = 2;
106   codec_info.codecSpecific.VP9.end_of_picture = false;
107 
108   RTPVideoHeader header =
109       params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
110 
111   EXPECT_EQ(kVideoRotation_90, header.rotation);
112   EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
113   EXPECT_EQ(kVideoCodecVP9, header.codec);
114   EXPECT_FALSE(header.color_space);
115   const auto& vp9_header =
116       absl::get<RTPVideoHeaderVP9>(header.video_type_header);
117   EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
118   EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
119   EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
120   EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
121   EXPECT_EQ(vp9_header.num_spatial_layers,
122             codec_info.codecSpecific.VP9.num_spatial_layers);
123   EXPECT_EQ(vp9_header.end_of_picture,
124             codec_info.codecSpecific.VP9.end_of_picture);
125 
126   // Next spatial layer.
127   codec_info.codecSpecific.VP9.first_frame_in_picture = false;
128   codec_info.codecSpecific.VP9.end_of_picture = true;
129 
130   encoded_image.SetSpatialIndex(1);
131   ColorSpace color_space(
132       ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
133       ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
134   encoded_image.SetColorSpace(color_space);
135   header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
136 
137   EXPECT_EQ(kVideoRotation_90, header.rotation);
138   EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
139   EXPECT_EQ(kVideoCodecVP9, header.codec);
140   EXPECT_EQ(absl::make_optional(color_space), header.color_space);
141   EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
142   EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
143   EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
144   EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
145   EXPECT_EQ(vp9_header.num_spatial_layers,
146             codec_info.codecSpecific.VP9.num_spatial_layers);
147   EXPECT_EQ(vp9_header.end_of_picture,
148             codec_info.codecSpecific.VP9.end_of_picture);
149 }
150 
TEST(RtpPayloadParamsTest,PictureIdIsSetForVp8)151 TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
152   RtpPayloadState state;
153   state.picture_id = kInitialPictureId1;
154   state.tl0_pic_idx = kInitialTl0PicIdx1;
155 
156   EncodedImage encoded_image;
157   CodecSpecificInfo codec_info;
158   codec_info.codecType = kVideoCodecVP8;
159 
160   RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
161   RTPVideoHeader header =
162       params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
163   EXPECT_EQ(kVideoCodecVP8, header.codec);
164   EXPECT_EQ(kInitialPictureId1 + 1,
165             absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
166 
167   // State should hold latest used picture id and tl0_pic_idx.
168   state = params.state();
169   EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
170   EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
171 }
172 
TEST(RtpPayloadParamsTest,PictureIdWraps)173 TEST(RtpPayloadParamsTest, PictureIdWraps) {
174   RtpPayloadState state;
175   state.picture_id = kMaxTwoBytePictureId;
176   state.tl0_pic_idx = kInitialTl0PicIdx1;
177 
178   EncodedImage encoded_image;
179   CodecSpecificInfo codec_info;
180   codec_info.codecType = kVideoCodecVP8;
181   codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
182 
183   RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
184   RTPVideoHeader header =
185       params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
186   EXPECT_EQ(kVideoCodecVP8, header.codec);
187   EXPECT_EQ(0,
188             absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
189 
190   // State should hold latest used picture id and tl0_pic_idx.
191   EXPECT_EQ(0, params.state().picture_id);  // Wrapped.
192   EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
193 }
194 
TEST(RtpPayloadParamsTest,Tl0PicIdxUpdatedForVp8)195 TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
196   RtpPayloadState state;
197   state.picture_id = kInitialPictureId1;
198   state.tl0_pic_idx = kInitialTl0PicIdx1;
199 
200   EncodedImage encoded_image;
201   // Modules are sending for this test.
202   // OnEncodedImage, temporalIdx: 1.
203   CodecSpecificInfo codec_info;
204   codec_info.codecType = kVideoCodecVP8;
205   codec_info.codecSpecific.VP8.temporalIdx = 1;
206 
207   RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
208   RTPVideoHeader header =
209       params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
210 
211   EXPECT_EQ(kVideoCodecVP8, header.codec);
212   const auto& vp8_header =
213       absl::get<RTPVideoHeaderVP8>(header.video_type_header);
214   EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
215   EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
216 
217   // OnEncodedImage, temporalIdx: 0.
218   codec_info.codecSpecific.VP8.temporalIdx = 0;
219 
220   header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
221   EXPECT_EQ(kVideoCodecVP8, header.codec);
222   EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
223   EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
224 
225   // State should hold latest used picture id and tl0_pic_idx.
226   EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
227   EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
228 }
229 
TEST(RtpPayloadParamsTest,Tl0PicIdxUpdatedForVp9)230 TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
231   RtpPayloadState state;
232   state.picture_id = kInitialPictureId1;
233   state.tl0_pic_idx = kInitialTl0PicIdx1;
234 
235   EncodedImage encoded_image;
236   // Modules are sending for this test.
237   // OnEncodedImage, temporalIdx: 1.
238   CodecSpecificInfo codec_info;
239   codec_info.codecType = kVideoCodecVP9;
240   codec_info.codecSpecific.VP9.temporal_idx = 1;
241   codec_info.codecSpecific.VP9.first_frame_in_picture = true;
242 
243   RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
244   RTPVideoHeader header =
245       params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
246 
247   EXPECT_EQ(kVideoCodecVP9, header.codec);
248   const auto& vp9_header =
249       absl::get<RTPVideoHeaderVP9>(header.video_type_header);
250   EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
251   EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
252 
253   // OnEncodedImage, temporalIdx: 0.
254   codec_info.codecSpecific.VP9.temporal_idx = 0;
255 
256   header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
257 
258   EXPECT_EQ(kVideoCodecVP9, header.codec);
259   EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
260   EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
261 
262   // OnEncodedImage, first_frame_in_picture = false
263   codec_info.codecSpecific.VP9.first_frame_in_picture = false;
264 
265   header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
266 
267   EXPECT_EQ(kVideoCodecVP9, header.codec);
268   EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
269   EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
270 
271   // State should hold latest used picture id and tl0_pic_idx.
272   EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
273   EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
274 }
275 
TEST(RtpPayloadParamsTest,PictureIdForOldGenericFormat)276 TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
277   test::ScopedFieldTrials generic_picture_id(
278       "WebRTC-GenericPictureId/Enabled/");
279   RtpPayloadState state{};
280 
281   EncodedImage encoded_image;
282   CodecSpecificInfo codec_info;
283   codec_info.codecType = kVideoCodecGeneric;
284   encoded_image._frameType = VideoFrameType::kVideoFrameKey;
285 
286   RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
287   RTPVideoHeader header =
288       params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
289 
290   EXPECT_EQ(kVideoCodecGeneric, header.codec);
291   const auto* generic =
292       absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
293   ASSERT_TRUE(generic);
294   EXPECT_EQ(0, generic->picture_id);
295 
296   encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
297   header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
298   generic =
299       absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
300   ASSERT_TRUE(generic);
301   EXPECT_EQ(1, generic->picture_id);
302 }
303 
TEST(RtpPayloadParamsTest,GenericDescriptorForGenericCodec)304 TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
305   RtpPayloadState state{};
306 
307   EncodedImage encoded_image;
308   encoded_image._frameType = VideoFrameType::kVideoFrameKey;
309   CodecSpecificInfo codec_info;
310   codec_info.codecType = kVideoCodecGeneric;
311 
312   RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
313   RTPVideoHeader header =
314       params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
315 
316   EXPECT_EQ(kVideoCodecGeneric, header.codec);
317   ASSERT_TRUE(header.generic);
318   EXPECT_EQ(0, header.generic->frame_id);
319   EXPECT_THAT(header.generic->dependencies, IsEmpty());
320 
321   encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
322   header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
323   ASSERT_TRUE(header.generic);
324   EXPECT_EQ(1, header.generic->frame_id);
325   EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
326 }
327 
TEST(RtpPayloadParamsTest,SetsGenericFromGenericFrameInfo)328 TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
329   RtpPayloadState state;
330   EncodedImage encoded_image;
331   CodecSpecificInfo codec_info;
332 
333   RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
334 
335   encoded_image._frameType = VideoFrameType::kVideoFrameKey;
336   codec_info.generic_frame_info =
337       GenericFrameInfo::Builder().S(1).T(0).Dtis("S").Build();
338   codec_info.generic_frame_info->encoder_buffers = {
339       {/*id=*/0, /*referenced=*/false, /*updated=*/true}};
340   codec_info.generic_frame_info->part_of_chain = {true, false};
341   RTPVideoHeader key_header =
342       params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/1);
343 
344   ASSERT_TRUE(key_header.generic);
345   EXPECT_EQ(key_header.generic->spatial_index, 1);
346   EXPECT_EQ(key_header.generic->temporal_index, 0);
347   EXPECT_EQ(key_header.generic->frame_id, 1);
348   EXPECT_THAT(key_header.generic->dependencies, IsEmpty());
349   EXPECT_THAT(key_header.generic->decode_target_indications,
350               ElementsAre(DecodeTargetIndication::kSwitch));
351   EXPECT_THAT(key_header.generic->chain_diffs, SizeIs(2));
352 
353   encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
354   codec_info.generic_frame_info =
355       GenericFrameInfo::Builder().S(2).T(3).Dtis("D").Build();
356   codec_info.generic_frame_info->encoder_buffers = {
357       {/*id=*/0, /*referenced=*/true, /*updated=*/false}};
358   codec_info.generic_frame_info->part_of_chain = {false, false};
359   RTPVideoHeader delta_header =
360       params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/3);
361 
362   ASSERT_TRUE(delta_header.generic);
363   EXPECT_EQ(delta_header.generic->spatial_index, 2);
364   EXPECT_EQ(delta_header.generic->temporal_index, 3);
365   EXPECT_EQ(delta_header.generic->frame_id, 3);
366   EXPECT_THAT(delta_header.generic->dependencies, ElementsAre(1));
367   EXPECT_THAT(delta_header.generic->decode_target_indications,
368               ElementsAre(DecodeTargetIndication::kDiscardable));
369   EXPECT_THAT(delta_header.generic->chain_diffs, SizeIs(2));
370 }
371 
372 class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
373  public:
374   enum LayerSync { kNoSync, kSync };
375 
RtpPayloadParamsVp8ToGenericTest()376   RtpPayloadParamsVp8ToGenericTest()
377       : state_(), params_(123, &state_, trials_config_) {}
378 
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)379   void ConvertAndCheck(int temporal_index,
380                        int64_t shared_frame_id,
381                        VideoFrameType frame_type,
382                        LayerSync layer_sync,
383                        const std::set<int64_t>& expected_deps,
384                        uint16_t width = 0,
385                        uint16_t height = 0) {
386     EncodedImage encoded_image;
387     encoded_image._frameType = frame_type;
388     encoded_image._encodedWidth = width;
389     encoded_image._encodedHeight = height;
390 
391     CodecSpecificInfo codec_info;
392     codec_info.codecType = kVideoCodecVP8;
393     codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
394     codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
395 
396     RTPVideoHeader header =
397         params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
398 
399     ASSERT_TRUE(header.generic);
400     EXPECT_EQ(header.generic->spatial_index, 0);
401 
402     EXPECT_EQ(header.generic->frame_id, shared_frame_id);
403     EXPECT_EQ(header.generic->temporal_index, temporal_index);
404     std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
405                                   header.generic->dependencies.end());
406     EXPECT_EQ(expected_deps, actual_deps);
407 
408     EXPECT_EQ(header.width, width);
409     EXPECT_EQ(header.height, height);
410   }
411 
412  protected:
413   FieldTrialBasedConfig trials_config_;
414   RtpPayloadState state_;
415   RtpPayloadParams params_;
416 };
417 
TEST_F(RtpPayloadParamsVp8ToGenericTest,Keyframe)418 TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
419   ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
420   ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
421   ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
422 }
423 
TEST_F(RtpPayloadParamsVp8ToGenericTest,TooHighTemporalIndex)424 TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
425   ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
426 
427   EncodedImage encoded_image;
428   encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
429   CodecSpecificInfo codec_info;
430   codec_info.codecType = kVideoCodecVP8;
431   codec_info.codecSpecific.VP8.temporalIdx =
432       RtpGenericFrameDescriptor::kMaxTemporalLayers;
433   codec_info.codecSpecific.VP8.layerSync = false;
434 
435   RTPVideoHeader header =
436       params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
437   EXPECT_FALSE(header.generic);
438 }
439 
TEST_F(RtpPayloadParamsVp8ToGenericTest,LayerSync)440 TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
441   // 02120212 pattern
442   ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
443   ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
444   ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
445   ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
446 
447   ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
448   ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
449   ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
450                   {4});  // layer sync
451   ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
452 }
453 
TEST_F(RtpPayloadParamsVp8ToGenericTest,FrameIdGaps)454 TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
455   // 0101 pattern
456   ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
457   ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
458 
459   ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
460   ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
461 
462   ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
463   ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
464 }
465 
466 class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
467  public:
468   enum LayerSync { kNoSync, kSync };
469 
RtpPayloadParamsH264ToGenericTest()470   RtpPayloadParamsH264ToGenericTest()
471       : state_(), params_(123, &state_, trials_config_) {}
472 
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)473   void ConvertAndCheck(int temporal_index,
474                        int64_t shared_frame_id,
475                        VideoFrameType frame_type,
476                        LayerSync layer_sync,
477                        const std::set<int64_t>& expected_deps,
478                        uint16_t width = 0,
479                        uint16_t height = 0) {
480     EncodedImage encoded_image;
481     encoded_image._frameType = frame_type;
482     encoded_image._encodedWidth = width;
483     encoded_image._encodedHeight = height;
484 
485     CodecSpecificInfo codec_info;
486     codec_info.codecType = kVideoCodecH264;
487     codec_info.codecSpecific.H264.temporal_idx = temporal_index;
488     codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
489 
490     RTPVideoHeader header =
491         params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
492 
493     ASSERT_TRUE(header.generic);
494     EXPECT_EQ(header.generic->spatial_index, 0);
495 
496     EXPECT_EQ(header.generic->frame_id, shared_frame_id);
497     EXPECT_EQ(header.generic->temporal_index, temporal_index);
498     std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
499                                   header.generic->dependencies.end());
500     EXPECT_EQ(expected_deps, actual_deps);
501 
502     EXPECT_EQ(header.width, width);
503     EXPECT_EQ(header.height, height);
504   }
505 
506  protected:
507   FieldTrialBasedConfig trials_config_;
508   RtpPayloadState state_;
509   RtpPayloadParams params_;
510 };
511 
TEST_F(RtpPayloadParamsH264ToGenericTest,Keyframe)512 TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
513   ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
514   ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
515   ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
516 }
517 
TEST_F(RtpPayloadParamsH264ToGenericTest,TooHighTemporalIndex)518 TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
519   ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
520 
521   EncodedImage encoded_image;
522   encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
523   CodecSpecificInfo codec_info;
524   codec_info.codecType = kVideoCodecH264;
525   codec_info.codecSpecific.H264.temporal_idx =
526       RtpGenericFrameDescriptor::kMaxTemporalLayers;
527   codec_info.codecSpecific.H264.base_layer_sync = false;
528 
529   RTPVideoHeader header =
530       params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
531   EXPECT_FALSE(header.generic);
532 }
533 
TEST_F(RtpPayloadParamsH264ToGenericTest,LayerSync)534 TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
535   // 02120212 pattern
536   ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
537   ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
538   ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
539   ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
540 
541   ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
542   ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
543   ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
544                   {4});  // layer sync
545   ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
546 }
547 
TEST_F(RtpPayloadParamsH264ToGenericTest,FrameIdGaps)548 TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
549   // 0101 pattern
550   ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
551   ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
552 
553   ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
554   ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
555 
556   ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
557   ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
558 }
559 
560 }  // namespace webrtc
561