blob: 1d6a70c1dbefb27b870d5440259637a7baf51be7 [file] [log] [blame]
Stefan Holmerf7044682018-07-17 10:16:41 +02001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "call/rtp_payload_params.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <map>
philipelbf2b6202018-08-27 14:33:18 +020016#include <set>
Stefan Holmerf7044682018-07-17 10:16:41 +020017
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "absl/container/inlined_vector.h"
19#include "absl/types/optional.h"
20#include "absl/types/variant.h"
Erik Språngcbc0cba2020-04-18 14:36:59 +020021#include "api/transport/field_trial_based_config.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "api/video/video_content_type.h"
23#include "api/video/video_rotation.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "modules/video_coding/codecs/h264/include/h264_globals.h"
25#include "modules/video_coding/codecs/interface/common_constants.h"
26#include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
27#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020028#include "modules/video_coding/include/video_codec_interface.h"
philipelbf2b6202018-08-27 14:33:18 +020029#include "test/field_trial.h"
philipel8aba8fe2019-06-13 15:13:16 +020030#include "test/gmock.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020031#include "test/gtest.h"
32
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010033using ::testing::ElementsAre;
34using ::testing::IsEmpty;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010035
Qingsi Wang1c1b99e2020-01-07 19:16:33 +000036namespace webrtc {
37namespace {
Stefan Holmerf7044682018-07-17 10:16:41 +020038const uint32_t kSsrc1 = 12345;
39const uint32_t kSsrc2 = 23456;
40const int16_t kPictureId = 123;
41const int16_t kTl0PicIdx = 20;
42const uint8_t kTemporalIdx = 1;
43const int16_t kInitialPictureId1 = 222;
44const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020045const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020046} // namespace
47
48TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
49 RtpPayloadState state2;
50 state2.picture_id = kPictureId;
51 state2.tl0_pic_idx = kTl0PicIdx;
52 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
53
Erik Språngcbc0cba2020-04-18 14:36:59 +020054 RtpPayloadParams params(kSsrc2, &state2, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020055 EncodedImage encoded_image;
56 encoded_image.rotation_ = kVideoRotation_90;
57 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020058 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020059
60 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020061 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020062 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020063 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020064 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020065 codec_info.codecSpecific.VP8.nonReference = true;
66
philipelbf2b6202018-08-27 14:33:18 +020067 RTPVideoHeader header =
68 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
69
70 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020071 codec_info.codecSpecific.VP8.temporalIdx = 1;
72 codec_info.codecSpecific.VP8.layerSync = true;
73
74 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020075
76 EXPECT_EQ(kVideoRotation_90, header.rotation);
77 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
78 EXPECT_EQ(1, header.simulcastIdx);
79 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +000080 const auto& vp8_header =
81 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
82 EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
83 EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
84 EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
85 EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
86 EXPECT_TRUE(vp8_header.layerSync);
87 EXPECT_TRUE(vp8_header.nonReference);
Stefan Holmerf7044682018-07-17 10:16:41 +020088}
89
90TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
91 RtpPayloadState state;
92 state.picture_id = kPictureId;
93 state.tl0_pic_idx = kTl0PicIdx;
Erik Språngcbc0cba2020-04-18 14:36:59 +020094 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020095
96 EncodedImage encoded_image;
97 encoded_image.rotation_ = kVideoRotation_90;
98 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020099 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +0200100 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200101 codec_info.codecType = kVideoCodecVP9;
102 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
103 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200104 codec_info.codecSpecific.VP9.temporal_idx = 2;
105 codec_info.codecSpecific.VP9.end_of_picture = false;
106
philipelbf2b6202018-08-27 14:33:18 +0200107 RTPVideoHeader header =
108 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200109
110 EXPECT_EQ(kVideoRotation_90, header.rotation);
111 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
112 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100113 EXPECT_FALSE(header.color_space);
philipel29d88462018-08-08 14:26:00 +0200114 const auto& vp9_header =
115 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
116 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
117 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
118 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200119 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200120 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200121 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200122 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200123 codec_info.codecSpecific.VP9.end_of_picture);
124
125 // Next spatial layer.
126 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200127 codec_info.codecSpecific.VP9.end_of_picture = true;
128
Niels Möllerd3b8c632018-08-27 15:33:42 +0200129 encoded_image.SetSpatialIndex(1);
Johannes Krond0b69a82018-12-03 14:18:53 +0100130 ColorSpace color_space(
131 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
132 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
Danil Chapovalovb7698942019-02-05 11:32:19 +0100133 encoded_image.SetColorSpace(color_space);
philipelbf2b6202018-08-27 14:33:18 +0200134 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200135
136 EXPECT_EQ(kVideoRotation_90, header.rotation);
137 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
138 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100139 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
philipel29d88462018-08-08 14:26:00 +0200140 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
141 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
142 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200143 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200144 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200145 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200146 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200147 codec_info.codecSpecific.VP9.end_of_picture);
148}
149
150TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_H264) {
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500151 RtpPayloadState state;
152 state.picture_id = kPictureId;
153 state.tl0_pic_idx = kInitialTl0PicIdx1;
Erik Språngcbc0cba2020-04-18 14:36:59 +0200154 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +0200155
156 EncodedImage encoded_image;
157 CodecSpecificInfo codec_info;
Jonas Olssona4d87372019-07-05 19:08:33 +0200158 CodecSpecificInfoH264* h264info = &codec_info.codecSpecific.H264;
Stefan Holmerf7044682018-07-17 10:16:41 +0200159 codec_info.codecType = kVideoCodecH264;
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500160 h264info->packetization_mode = H264PacketizationMode::SingleNalUnit;
161 h264info->temporal_idx = kNoTemporalIdx;
Stefan Holmerf7044682018-07-17 10:16:41 +0200162
philipelbf2b6202018-08-27 14:33:18 +0200163 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100164 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
Stefan Holmerf7044682018-07-17 10:16:41 +0200165
166 EXPECT_EQ(0, header.simulcastIdx);
167 EXPECT_EQ(kVideoCodecH264, header.codec);
168 const auto& h264 = absl::get<RTPVideoHeaderH264>(header.video_type_header);
169 EXPECT_EQ(H264PacketizationMode::SingleNalUnit, h264.packetization_mode);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500170
171 // test temporal param 1
172 h264info->temporal_idx = 1;
173 h264info->base_layer_sync = true;
174 h264info->idr_frame = false;
175
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100176 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500177
178 EXPECT_EQ(kVideoCodecH264, header.codec);
179 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1);
180 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
181 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
182 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
183
184 // test temporal param 2
185 h264info->temporal_idx = 0;
186 h264info->base_layer_sync = false;
187 h264info->idr_frame = true;
188
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100189 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 30);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500190
191 EXPECT_EQ(kVideoCodecH264, header.codec);
192 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1 + 1);
193 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
194 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
195 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
Stefan Holmerf7044682018-07-17 10:16:41 +0200196}
197
198TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
199 RtpPayloadState state;
200 state.picture_id = kInitialPictureId1;
201 state.tl0_pic_idx = kInitialTl0PicIdx1;
202
203 EncodedImage encoded_image;
204 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200205 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200206
Erik Språngcbc0cba2020-04-18 14:36:59 +0200207 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200208 RTPVideoHeader header =
209 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200210 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000211 EXPECT_EQ(kInitialPictureId1 + 1,
212 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200213
214 // State should hold latest used picture id and tl0_pic_idx.
215 state = params.state();
216 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
217 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
218}
219
220TEST(RtpPayloadParamsTest, PictureIdWraps) {
221 RtpPayloadState state;
222 state.picture_id = kMaxTwoBytePictureId;
223 state.tl0_pic_idx = kInitialTl0PicIdx1;
224
225 EncodedImage encoded_image;
226 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200227 codec_info.codecType = kVideoCodecVP8;
228 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
229
Erik Språngcbc0cba2020-04-18 14:36:59 +0200230 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200231 RTPVideoHeader header =
232 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200233 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000234 EXPECT_EQ(0,
235 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200236
237 // State should hold latest used picture id and tl0_pic_idx.
238 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
239 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
240}
241
242TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
243 RtpPayloadState state;
244 state.picture_id = kInitialPictureId1;
245 state.tl0_pic_idx = kInitialTl0PicIdx1;
246
247 EncodedImage encoded_image;
248 // Modules are sending for this test.
249 // OnEncodedImage, temporalIdx: 1.
250 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200251 codec_info.codecType = kVideoCodecVP8;
252 codec_info.codecSpecific.VP8.temporalIdx = 1;
253
Erik Språngcbc0cba2020-04-18 14:36:59 +0200254 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200255 RTPVideoHeader header =
256 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200257
258 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000259 const auto& vp8_header =
260 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
261 EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
262 EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200263
264 // OnEncodedImage, temporalIdx: 0.
265 codec_info.codecSpecific.VP8.temporalIdx = 0;
266
philipelbf2b6202018-08-27 14:33:18 +0200267 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200268 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000269 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
270 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200271
272 // State should hold latest used picture id and tl0_pic_idx.
273 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
274 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
275}
276
277TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
278 RtpPayloadState state;
279 state.picture_id = kInitialPictureId1;
280 state.tl0_pic_idx = kInitialTl0PicIdx1;
281
282 EncodedImage encoded_image;
283 // Modules are sending for this test.
284 // OnEncodedImage, temporalIdx: 1.
285 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200286 codec_info.codecType = kVideoCodecVP9;
287 codec_info.codecSpecific.VP9.temporal_idx = 1;
288 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
289
Erik Språngcbc0cba2020-04-18 14:36:59 +0200290 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200291 RTPVideoHeader header =
292 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200293
294 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200295 const auto& vp9_header =
296 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
297 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
298 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200299
300 // OnEncodedImage, temporalIdx: 0.
301 codec_info.codecSpecific.VP9.temporal_idx = 0;
302
philipelbf2b6202018-08-27 14:33:18 +0200303 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200304
305 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200306 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
307 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200308
309 // OnEncodedImage, first_frame_in_picture = false
310 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
311
philipelbf2b6202018-08-27 14:33:18 +0200312 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200313
314 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200315 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
316 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200317
318 // State should hold latest used picture id and tl0_pic_idx.
319 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
320 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
321}
philipelbf2b6202018-08-27 14:33:18 +0200322
323TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
324 test::ScopedFieldTrials generic_picture_id(
325 "WebRTC-GenericPictureId/Enabled/");
326 RtpPayloadState state{};
327
328 EncodedImage encoded_image;
philipeld1d03592019-03-01 13:53:55 +0100329 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200330 codec_info.codecType = kVideoCodecGeneric;
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100331 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
philipelbf2b6202018-08-27 14:33:18 +0200332
Erik Språngcbc0cba2020-04-18 14:36:59 +0200333 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200334 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100335 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
philipelbf2b6202018-08-27 14:33:18 +0200336
337 EXPECT_EQ(kVideoCodecGeneric, header.codec);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100338 const auto* generic =
339 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
340 ASSERT_TRUE(generic);
341 EXPECT_EQ(0, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200342
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100343 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
344 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100345 generic =
346 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
347 ASSERT_TRUE(generic);
348 EXPECT_EQ(1, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200349}
350
philipel8aba8fe2019-06-13 15:13:16 +0200351TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
352 test::ScopedFieldTrials generic_picture_id(
353 "WebRTC-GenericDescriptor/Enabled/");
354 RtpPayloadState state{};
355
356 EncodedImage encoded_image;
357 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
358 CodecSpecificInfo codec_info;
359 codec_info.codecType = kVideoCodecGeneric;
360
Erik Språngcbc0cba2020-04-18 14:36:59 +0200361 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipel8aba8fe2019-06-13 15:13:16 +0200362 RTPVideoHeader header =
363 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
364
365 EXPECT_EQ(kVideoCodecGeneric, header.codec);
366 ASSERT_TRUE(header.generic);
367 EXPECT_EQ(0, header.generic->frame_id);
368 EXPECT_THAT(header.generic->dependencies, IsEmpty());
369
370 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
371 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
372 ASSERT_TRUE(header.generic);
373 EXPECT_EQ(1, header.generic->frame_id);
374 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
375}
376
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100377TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
378 test::ScopedFieldTrials generic_picture_id(
379 "WebRTC-GenericDescriptor/Enabled/");
380 RtpPayloadState state;
381 EncodedImage encoded_image;
382 CodecSpecificInfo codec_info;
383
Erik Språngcbc0cba2020-04-18 14:36:59 +0200384 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100385
386 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
387 codec_info.generic_frame_info =
388 GenericFrameInfo::Builder().S(1).T(0).Dtis("S").Build();
389 codec_info.generic_frame_info->encoder_buffers = {
390 {/*id=*/0, /*referenced=*/false, /*updated=*/true}};
391 RTPVideoHeader key_header =
392 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/1);
393
394 ASSERT_TRUE(key_header.generic);
395 EXPECT_EQ(key_header.generic->spatial_index, 1);
396 EXPECT_EQ(key_header.generic->temporal_index, 0);
397 EXPECT_EQ(key_header.generic->frame_id, 1);
398 EXPECT_THAT(key_header.generic->dependencies, IsEmpty());
399 EXPECT_THAT(key_header.generic->decode_target_indications,
400 ElementsAre(DecodeTargetIndication::kSwitch));
401 EXPECT_FALSE(key_header.generic->discardable);
402
403 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
404 codec_info.generic_frame_info =
405 GenericFrameInfo::Builder().S(2).T(3).Dtis("D").Build();
406 codec_info.generic_frame_info->encoder_buffers = {
407 {/*id=*/0, /*referenced=*/true, /*updated=*/false}};
408 RTPVideoHeader delta_header =
409 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/3);
410
411 ASSERT_TRUE(delta_header.generic);
412 EXPECT_EQ(delta_header.generic->spatial_index, 2);
413 EXPECT_EQ(delta_header.generic->temporal_index, 3);
414 EXPECT_EQ(delta_header.generic->frame_id, 3);
415 EXPECT_THAT(delta_header.generic->dependencies, ElementsAre(1));
416 EXPECT_THAT(delta_header.generic->decode_target_indications,
417 ElementsAre(DecodeTargetIndication::kDiscardable));
418 EXPECT_TRUE(delta_header.generic->discardable);
419}
420
philipelbf2b6202018-08-27 14:33:18 +0200421class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
422 public:
423 enum LayerSync { kNoSync, kSync };
424
philipel569397f2018-09-26 12:25:31 +0200425 RtpPayloadParamsVp8ToGenericTest()
426 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
427 state_(),
Erik Språngcbc0cba2020-04-18 14:36:59 +0200428 params_(123, &state_, trials_config_) {}
philipelbf2b6202018-08-27 14:33:18 +0200429
430 void ConvertAndCheck(int temporal_index,
431 int64_t shared_frame_id,
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000432 VideoFrameType frame_type,
philipelbf2b6202018-08-27 14:33:18 +0200433 LayerSync layer_sync,
philipelfab91292018-10-17 14:36:08 +0200434 const std::set<int64_t>& expected_deps,
435 uint16_t width = 0,
436 uint16_t height = 0) {
philipelbf2b6202018-08-27 14:33:18 +0200437 EncodedImage encoded_image;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000438 encoded_image._frameType = frame_type;
philipelfab91292018-10-17 14:36:08 +0200439 encoded_image._encodedWidth = width;
440 encoded_image._encodedHeight = height;
philipelbf2b6202018-08-27 14:33:18 +0200441
philipeld1d03592019-03-01 13:53:55 +0100442 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200443 codec_info.codecType = kVideoCodecVP8;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000444 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
445 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
philipelbf2b6202018-08-27 14:33:18 +0200446
447 RTPVideoHeader header =
448 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
449
450 ASSERT_TRUE(header.generic);
philipelbf2b6202018-08-27 14:33:18 +0200451 EXPECT_EQ(header.generic->spatial_index, 0);
452
453 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
454 EXPECT_EQ(header.generic->temporal_index, temporal_index);
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000455 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
456 header.generic->dependencies.end());
457 EXPECT_EQ(expected_deps, actual_deps);
philipelfab91292018-10-17 14:36:08 +0200458
459 EXPECT_EQ(header.width, width);
460 EXPECT_EQ(header.height, height);
philipelbf2b6202018-08-27 14:33:18 +0200461 }
462
463 protected:
philipel569397f2018-09-26 12:25:31 +0200464 test::ScopedFieldTrials generic_descriptor_field_trial_;
Erik Språngcbc0cba2020-04-18 14:36:59 +0200465 FieldTrialBasedConfig trials_config_;
philipelbf2b6202018-08-27 14:33:18 +0200466 RtpPayloadState state_;
467 RtpPayloadParams params_;
468};
469
470TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000471 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
472 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
473 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200474}
475
476TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000477 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200478
479 EncodedImage encoded_image;
Niels Möller8f7ce222019-03-21 15:43:58 +0100480 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipeld1d03592019-03-01 13:53:55 +0100481 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200482 codec_info.codecType = kVideoCodecVP8;
483 codec_info.codecSpecific.VP8.temporalIdx =
484 RtpGenericFrameDescriptor::kMaxTemporalLayers;
485 codec_info.codecSpecific.VP8.layerSync = false;
486
487 RTPVideoHeader header =
488 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
489 EXPECT_FALSE(header.generic);
490}
491
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000492TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
493 // 02120212 pattern
494 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
495 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
496 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
497 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
philipelbf2b6202018-08-27 14:33:18 +0200498
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000499 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
500 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
501 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
502 {4}); // layer sync
503 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
philipelbf2b6202018-08-27 14:33:18 +0200504}
505
506TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
507 // 0101 pattern
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000508 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
509 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
philipelbf2b6202018-08-27 14:33:18 +0200510
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000511 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
512 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
philipelbf2b6202018-08-27 14:33:18 +0200513
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000514 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
515 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
philipelbf2b6202018-08-27 14:33:18 +0200516}
517
philipel8aba8fe2019-06-13 15:13:16 +0200518class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
519 public:
520 enum LayerSync { kNoSync, kSync };
521
522 RtpPayloadParamsH264ToGenericTest()
523 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
524 state_(),
Erik Språngcbc0cba2020-04-18 14:36:59 +0200525 params_(123, &state_, trials_config_) {}
philipel8aba8fe2019-06-13 15:13:16 +0200526
527 void ConvertAndCheck(int temporal_index,
528 int64_t shared_frame_id,
529 VideoFrameType frame_type,
530 LayerSync layer_sync,
531 const std::set<int64_t>& expected_deps,
532 uint16_t width = 0,
533 uint16_t height = 0) {
534 EncodedImage encoded_image;
535 encoded_image._frameType = frame_type;
536 encoded_image._encodedWidth = width;
537 encoded_image._encodedHeight = height;
538
539 CodecSpecificInfo codec_info;
540 codec_info.codecType = kVideoCodecH264;
541 codec_info.codecSpecific.H264.temporal_idx = temporal_index;
542 codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
543
544 RTPVideoHeader header =
545 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
546
547 ASSERT_TRUE(header.generic);
philipel8aba8fe2019-06-13 15:13:16 +0200548 EXPECT_EQ(header.generic->spatial_index, 0);
549
550 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
551 EXPECT_EQ(header.generic->temporal_index, temporal_index);
552 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
553 header.generic->dependencies.end());
554 EXPECT_EQ(expected_deps, actual_deps);
555
556 EXPECT_EQ(header.width, width);
557 EXPECT_EQ(header.height, height);
558 }
559
560 protected:
561 test::ScopedFieldTrials generic_descriptor_field_trial_;
Erik Språngcbc0cba2020-04-18 14:36:59 +0200562 FieldTrialBasedConfig trials_config_;
philipel8aba8fe2019-06-13 15:13:16 +0200563 RtpPayloadState state_;
564 RtpPayloadParams params_;
565};
566
567TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
568 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
569 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
570 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
571}
572
573TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
574 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
575
576 EncodedImage encoded_image;
577 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
578 CodecSpecificInfo codec_info;
579 codec_info.codecType = kVideoCodecH264;
580 codec_info.codecSpecific.H264.temporal_idx =
581 RtpGenericFrameDescriptor::kMaxTemporalLayers;
582 codec_info.codecSpecific.H264.base_layer_sync = false;
583
584 RTPVideoHeader header =
585 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
586 EXPECT_FALSE(header.generic);
587}
588
589TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
590 // 02120212 pattern
591 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
592 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
593 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
594 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
595
596 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
597 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
598 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
599 {4}); // layer sync
600 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
601}
602
603TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
604 // 0101 pattern
605 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
606 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
607
608 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
609 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
610
611 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
612 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
613}
614
Stefan Holmerf7044682018-07-17 10:16:41 +0200615} // namespace webrtc