blob: 00003484a9472427aecbec558ad92074fd15d283 [file] [log] [blame]
Stefan Holmerf7044682018-07-17 10:16:41 +02001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <string.h>
12#include <map>
philipelbf2b6202018-08-27 14:33:18 +020013#include <set>
Stefan Holmerf7044682018-07-17 10:16:41 +020014
Yves Gerey3e707812018-11-28 16:47:49 +010015#include "absl/container/inlined_vector.h"
16#include "absl/types/optional.h"
17#include "absl/types/variant.h"
18#include "api/video/video_content_type.h"
19#include "api/video/video_rotation.h"
Stefan Holmer9416ef82018-07-19 10:34:38 +020020#include "call/rtp_payload_params.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "modules/video_coding/codecs/h264/include/h264_globals.h"
22#include "modules/video_coding/codecs/interface/common_constants.h"
23#include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
24#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020025#include "modules/video_coding/include/video_codec_interface.h"
philipelbf2b6202018-08-27 14:33:18 +020026#include "test/field_trial.h"
philipel8aba8fe2019-06-13 15:13:16 +020027#include "test/gmock.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020028#include "test/gtest.h"
29
philipel8aba8fe2019-06-13 15:13:16 +020030using ::testing::ElementsAre;
31using ::testing::IsEmpty;
32
Stefan Holmerf7044682018-07-17 10:16:41 +020033namespace webrtc {
34namespace {
35const uint32_t kSsrc1 = 12345;
36const uint32_t kSsrc2 = 23456;
37const int16_t kPictureId = 123;
38const int16_t kTl0PicIdx = 20;
39const uint8_t kTemporalIdx = 1;
40const int16_t kInitialPictureId1 = 222;
41const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020042const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020043} // namespace
44
45TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
46 RtpPayloadState state2;
47 state2.picture_id = kPictureId;
48 state2.tl0_pic_idx = kTl0PicIdx;
49 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
50
51 RtpPayloadParams params(kSsrc2, &state2);
52 EncodedImage encoded_image;
53 encoded_image.rotation_ = kVideoRotation_90;
54 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020055 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020056
57 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020058 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020059 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020060 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020061 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020062 codec_info.codecSpecific.VP8.nonReference = true;
63
philipelbf2b6202018-08-27 14:33:18 +020064 RTPVideoHeader header =
65 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
66
67 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020068 codec_info.codecSpecific.VP8.temporalIdx = 1;
69 codec_info.codecSpecific.VP8.layerSync = true;
70
71 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020072
73 EXPECT_EQ(kVideoRotation_90, header.rotation);
74 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
75 EXPECT_EQ(1, header.simulcastIdx);
76 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +000077 const auto& vp8_header =
78 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
79 EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
80 EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
81 EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
82 EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
83 EXPECT_TRUE(vp8_header.layerSync);
84 EXPECT_TRUE(vp8_header.nonReference);
Stefan Holmerf7044682018-07-17 10:16:41 +020085}
86
87TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
88 RtpPayloadState state;
89 state.picture_id = kPictureId;
90 state.tl0_pic_idx = kTl0PicIdx;
91 RtpPayloadParams params(kSsrc1, &state);
92
93 EncodedImage encoded_image;
94 encoded_image.rotation_ = kVideoRotation_90;
95 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020096 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +020097 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020098 codec_info.codecType = kVideoCodecVP9;
99 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
100 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200101 codec_info.codecSpecific.VP9.temporal_idx = 2;
102 codec_info.codecSpecific.VP9.end_of_picture = false;
103
philipelbf2b6202018-08-27 14:33:18 +0200104 RTPVideoHeader header =
105 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200106
107 EXPECT_EQ(kVideoRotation_90, header.rotation);
108 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
109 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100110 EXPECT_FALSE(header.color_space);
philipel29d88462018-08-08 14:26:00 +0200111 const auto& vp9_header =
112 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
113 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
114 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
115 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200116 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200117 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200118 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200119 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200120 codec_info.codecSpecific.VP9.end_of_picture);
121
122 // Next spatial layer.
123 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200124 codec_info.codecSpecific.VP9.end_of_picture = true;
125
Niels Möllerd3b8c632018-08-27 15:33:42 +0200126 encoded_image.SetSpatialIndex(1);
Johannes Krond0b69a82018-12-03 14:18:53 +0100127 ColorSpace color_space(
128 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
129 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
Danil Chapovalovb7698942019-02-05 11:32:19 +0100130 encoded_image.SetColorSpace(color_space);
philipelbf2b6202018-08-27 14:33:18 +0200131 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200132
133 EXPECT_EQ(kVideoRotation_90, header.rotation);
134 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
135 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100136 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
philipel29d88462018-08-08 14:26:00 +0200137 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
138 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
139 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200140 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200141 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200142 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200143 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200144 codec_info.codecSpecific.VP9.end_of_picture);
145}
146
147TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_H264) {
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500148 RtpPayloadState state;
149 state.picture_id = kPictureId;
150 state.tl0_pic_idx = kInitialTl0PicIdx1;
151 RtpPayloadParams params(kSsrc1, &state);
Stefan Holmerf7044682018-07-17 10:16:41 +0200152
153 EncodedImage encoded_image;
154 CodecSpecificInfo codec_info;
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500155 CodecSpecificInfoH264 *h264info = &codec_info.codecSpecific.H264;
Stefan Holmerf7044682018-07-17 10:16:41 +0200156 codec_info.codecType = kVideoCodecH264;
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500157 h264info->packetization_mode = H264PacketizationMode::SingleNalUnit;
158 h264info->temporal_idx = kNoTemporalIdx;
Stefan Holmerf7044682018-07-17 10:16:41 +0200159
philipelbf2b6202018-08-27 14:33:18 +0200160 RTPVideoHeader header =
161 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200162
163 EXPECT_EQ(0, header.simulcastIdx);
164 EXPECT_EQ(kVideoCodecH264, header.codec);
165 const auto& h264 = absl::get<RTPVideoHeaderH264>(header.video_type_header);
166 EXPECT_EQ(H264PacketizationMode::SingleNalUnit, h264.packetization_mode);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500167
168 // test temporal param 1
169 h264info->temporal_idx = 1;
170 h264info->base_layer_sync = true;
171 h264info->idr_frame = false;
172
173 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
174
175 EXPECT_EQ(kVideoCodecH264, header.codec);
176 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1);
177 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
178 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
179 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
180
181 // test temporal param 2
182 h264info->temporal_idx = 0;
183 h264info->base_layer_sync = false;
184 h264info->idr_frame = true;
185
186 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
187
188 EXPECT_EQ(kVideoCodecH264, header.codec);
189 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1 + 1);
190 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
191 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
192 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
Stefan Holmerf7044682018-07-17 10:16:41 +0200193}
194
195TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
196 RtpPayloadState state;
197 state.picture_id = kInitialPictureId1;
198 state.tl0_pic_idx = kInitialTl0PicIdx1;
199
200 EncodedImage encoded_image;
201 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200202 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200203
204 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200205 RTPVideoHeader header =
206 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200207 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000208 EXPECT_EQ(kInitialPictureId1 + 1,
209 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200210
211 // State should hold latest used picture id and tl0_pic_idx.
212 state = params.state();
213 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
214 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
215}
216
217TEST(RtpPayloadParamsTest, PictureIdWraps) {
218 RtpPayloadState state;
219 state.picture_id = kMaxTwoBytePictureId;
220 state.tl0_pic_idx = kInitialTl0PicIdx1;
221
222 EncodedImage encoded_image;
223 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200224 codec_info.codecType = kVideoCodecVP8;
225 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
226
227 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200228 RTPVideoHeader header =
229 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200230 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000231 EXPECT_EQ(0,
232 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200233
234 // State should hold latest used picture id and tl0_pic_idx.
235 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
236 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
237}
238
239TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
240 RtpPayloadState state;
241 state.picture_id = kInitialPictureId1;
242 state.tl0_pic_idx = kInitialTl0PicIdx1;
243
244 EncodedImage encoded_image;
245 // Modules are sending for this test.
246 // OnEncodedImage, temporalIdx: 1.
247 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200248 codec_info.codecType = kVideoCodecVP8;
249 codec_info.codecSpecific.VP8.temporalIdx = 1;
250
251 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200252 RTPVideoHeader header =
253 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200254
255 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000256 const auto& vp8_header =
257 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
258 EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
259 EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200260
261 // OnEncodedImage, temporalIdx: 0.
262 codec_info.codecSpecific.VP8.temporalIdx = 0;
263
philipelbf2b6202018-08-27 14:33:18 +0200264 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200265 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000266 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
267 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200268
269 // State should hold latest used picture id and tl0_pic_idx.
270 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
271 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
272}
273
274TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
275 RtpPayloadState state;
276 state.picture_id = kInitialPictureId1;
277 state.tl0_pic_idx = kInitialTl0PicIdx1;
278
279 EncodedImage encoded_image;
280 // Modules are sending for this test.
281 // OnEncodedImage, temporalIdx: 1.
282 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200283 codec_info.codecType = kVideoCodecVP9;
284 codec_info.codecSpecific.VP9.temporal_idx = 1;
285 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
286
287 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200288 RTPVideoHeader header =
289 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200290
291 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200292 const auto& vp9_header =
293 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
294 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
295 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200296
297 // OnEncodedImage, temporalIdx: 0.
298 codec_info.codecSpecific.VP9.temporal_idx = 0;
299
philipelbf2b6202018-08-27 14:33:18 +0200300 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200301
302 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200303 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
304 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200305
306 // OnEncodedImage, first_frame_in_picture = false
307 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
308
philipelbf2b6202018-08-27 14:33:18 +0200309 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200310
311 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200312 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
313 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200314
315 // State should hold latest used picture id and tl0_pic_idx.
316 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
317 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
318}
philipelbf2b6202018-08-27 14:33:18 +0200319
320TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
321 test::ScopedFieldTrials generic_picture_id(
322 "WebRTC-GenericPictureId/Enabled/");
323 RtpPayloadState state{};
324
325 EncodedImage encoded_image;
philipeld1d03592019-03-01 13:53:55 +0100326 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200327 codec_info.codecType = kVideoCodecGeneric;
328
329 RtpPayloadParams params(kSsrc1, &state);
330 RTPVideoHeader header =
331 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
332
333 EXPECT_EQ(kVideoCodecGeneric, header.codec);
334 ASSERT_TRUE(header.generic);
335 EXPECT_EQ(0, header.generic->frame_id);
336
337 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
338 ASSERT_TRUE(header.generic);
339 EXPECT_EQ(1, header.generic->frame_id);
340}
341
philipel8aba8fe2019-06-13 15:13:16 +0200342TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
343 test::ScopedFieldTrials generic_picture_id(
344 "WebRTC-GenericDescriptor/Enabled/");
345 RtpPayloadState state{};
346
347 EncodedImage encoded_image;
348 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
349 CodecSpecificInfo codec_info;
350 codec_info.codecType = kVideoCodecGeneric;
351
352 RtpPayloadParams params(kSsrc1, &state);
353 RTPVideoHeader header =
354 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
355
356 EXPECT_EQ(kVideoCodecGeneric, header.codec);
357 ASSERT_TRUE(header.generic);
358 EXPECT_EQ(0, header.generic->frame_id);
359 EXPECT_THAT(header.generic->dependencies, IsEmpty());
360
361 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
362 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
363 ASSERT_TRUE(header.generic);
364 EXPECT_EQ(1, header.generic->frame_id);
365 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
366}
367
philipelbf2b6202018-08-27 14:33:18 +0200368class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
369 public:
370 enum LayerSync { kNoSync, kSync };
371
philipel569397f2018-09-26 12:25:31 +0200372 RtpPayloadParamsVp8ToGenericTest()
373 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
374 state_(),
375 params_(123, &state_) {}
philipelbf2b6202018-08-27 14:33:18 +0200376
377 void ConvertAndCheck(int temporal_index,
378 int64_t shared_frame_id,
Niels Möller87e2d782019-03-07 10:18:23 +0100379 VideoFrameType frame_type,
philipelbf2b6202018-08-27 14:33:18 +0200380 LayerSync layer_sync,
philipelfab91292018-10-17 14:36:08 +0200381 const std::set<int64_t>& expected_deps,
382 uint16_t width = 0,
383 uint16_t height = 0) {
philipelbf2b6202018-08-27 14:33:18 +0200384 EncodedImage encoded_image;
385 encoded_image._frameType = frame_type;
philipelfab91292018-10-17 14:36:08 +0200386 encoded_image._encodedWidth = width;
387 encoded_image._encodedHeight = height;
philipelbf2b6202018-08-27 14:33:18 +0200388
philipeld1d03592019-03-01 13:53:55 +0100389 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200390 codec_info.codecType = kVideoCodecVP8;
391 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
392 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
393
394 RTPVideoHeader header =
395 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
396
397 ASSERT_TRUE(header.generic);
398 EXPECT_TRUE(header.generic->higher_spatial_layers.empty());
399 EXPECT_EQ(header.generic->spatial_index, 0);
400
401 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
402 EXPECT_EQ(header.generic->temporal_index, temporal_index);
403 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
404 header.generic->dependencies.end());
405 EXPECT_EQ(expected_deps, actual_deps);
philipelfab91292018-10-17 14:36:08 +0200406
407 EXPECT_EQ(header.width, width);
408 EXPECT_EQ(header.height, height);
philipelbf2b6202018-08-27 14:33:18 +0200409 }
410
411 protected:
philipel569397f2018-09-26 12:25:31 +0200412 test::ScopedFieldTrials generic_descriptor_field_trial_;
philipelbf2b6202018-08-27 14:33:18 +0200413 RtpPayloadState state_;
414 RtpPayloadParams params_;
415};
416
417TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100418 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
419 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
420 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200421}
422
423TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100424 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200425
426 EncodedImage encoded_image;
Niels Möller8f7ce222019-03-21 15:43:58 +0100427 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipeld1d03592019-03-01 13:53:55 +0100428 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200429 codec_info.codecType = kVideoCodecVP8;
430 codec_info.codecSpecific.VP8.temporalIdx =
431 RtpGenericFrameDescriptor::kMaxTemporalLayers;
432 codec_info.codecSpecific.VP8.layerSync = false;
433
434 RTPVideoHeader header =
435 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
436 EXPECT_FALSE(header.generic);
437}
438
439TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
440 // 02120212 pattern
Niels Möller8f7ce222019-03-21 15:43:58 +0100441 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
442 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
443 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
444 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
philipelbf2b6202018-08-27 14:33:18 +0200445
Niels Möller8f7ce222019-03-21 15:43:58 +0100446 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
447 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
448 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
449 {4}); // layer sync
450 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
philipelbf2b6202018-08-27 14:33:18 +0200451}
452
453TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
454 // 0101 pattern
Niels Möller8f7ce222019-03-21 15:43:58 +0100455 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
456 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
philipelbf2b6202018-08-27 14:33:18 +0200457
Niels Möller8f7ce222019-03-21 15:43:58 +0100458 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
459 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
philipelbf2b6202018-08-27 14:33:18 +0200460
Niels Möller8f7ce222019-03-21 15:43:58 +0100461 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
462 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
philipelbf2b6202018-08-27 14:33:18 +0200463}
464
philipel8aba8fe2019-06-13 15:13:16 +0200465class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
466 public:
467 enum LayerSync { kNoSync, kSync };
468
469 RtpPayloadParamsH264ToGenericTest()
470 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
471 state_(),
472 params_(123, &state_) {}
473
474 void ConvertAndCheck(int temporal_index,
475 int64_t shared_frame_id,
476 VideoFrameType frame_type,
477 LayerSync layer_sync,
478 const std::set<int64_t>& expected_deps,
479 uint16_t width = 0,
480 uint16_t height = 0) {
481 EncodedImage encoded_image;
482 encoded_image._frameType = frame_type;
483 encoded_image._encodedWidth = width;
484 encoded_image._encodedHeight = height;
485
486 CodecSpecificInfo codec_info;
487 codec_info.codecType = kVideoCodecH264;
488 codec_info.codecSpecific.H264.temporal_idx = temporal_index;
489 codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
490
491 RTPVideoHeader header =
492 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
493
494 ASSERT_TRUE(header.generic);
495 EXPECT_TRUE(header.generic->higher_spatial_layers.empty());
496 EXPECT_EQ(header.generic->spatial_index, 0);
497
498 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
499 EXPECT_EQ(header.generic->temporal_index, temporal_index);
500 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
501 header.generic->dependencies.end());
502 EXPECT_EQ(expected_deps, actual_deps);
503
504 EXPECT_EQ(header.width, width);
505 EXPECT_EQ(header.height, height);
506 }
507
508 protected:
509 test::ScopedFieldTrials generic_descriptor_field_trial_;
510 RtpPayloadState state_;
511 RtpPayloadParams params_;
512};
513
514TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
515 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
516 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
517 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
518}
519
520TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
521 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
522
523 EncodedImage encoded_image;
524 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
525 CodecSpecificInfo codec_info;
526 codec_info.codecType = kVideoCodecH264;
527 codec_info.codecSpecific.H264.temporal_idx =
528 RtpGenericFrameDescriptor::kMaxTemporalLayers;
529 codec_info.codecSpecific.H264.base_layer_sync = false;
530
531 RTPVideoHeader header =
532 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
533 EXPECT_FALSE(header.generic);
534}
535
536TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
537 // 02120212 pattern
538 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
539 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
540 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
541 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
542
543 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
544 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
545 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
546 {4}); // layer sync
547 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
548}
549
550TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
551 // 0101 pattern
552 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
553 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
554
555 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
556 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
557
558 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
559 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
560}
561
Stefan Holmerf7044682018-07-17 10:16:41 +0200562} // namespace webrtc