blob: 75860a806e2b94126524db587edd82fd681fb2d1 [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 Chapovalov4b860c12020-05-19 14:48:19 +020035using ::testing::SizeIs;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010036
Qingsi Wang1c1b99e2020-01-07 19:16:33 +000037namespace webrtc {
38namespace {
Stefan Holmerf7044682018-07-17 10:16:41 +020039const uint32_t kSsrc1 = 12345;
40const uint32_t kSsrc2 = 23456;
41const int16_t kPictureId = 123;
42const int16_t kTl0PicIdx = 20;
43const uint8_t kTemporalIdx = 1;
44const int16_t kInitialPictureId1 = 222;
45const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020046const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020047} // namespace
48
49TEST(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
Erik Språngcbc0cba2020-04-18 14:36:59 +020055 RtpPayloadParams params(kSsrc2, &state2, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020056 EncodedImage encoded_image;
57 encoded_image.rotation_ = kVideoRotation_90;
58 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020059 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020060
61 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020062 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020063 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020064 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020065 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020066 codec_info.codecSpecific.VP8.nonReference = true;
67
philipelbf2b6202018-08-27 14:33:18 +020068 RTPVideoHeader header =
69 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
70
71 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020072 codec_info.codecSpecific.VP8.temporalIdx = 1;
73 codec_info.codecSpecific.VP8.layerSync = true;
74
75 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020076
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);
Philip Eliassond52a1a62018-09-07 13:03:55 +000081 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);
Stefan Holmerf7044682018-07-17 10:16:41 +020089}
90
91TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
92 RtpPayloadState state;
93 state.picture_id = kPictureId;
94 state.tl0_pic_idx = kTl0PicIdx;
Erik Språngcbc0cba2020-04-18 14:36:59 +020095 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +020096
97 EncodedImage encoded_image;
98 encoded_image.rotation_ = kVideoRotation_90;
99 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200100 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +0200101 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200102 codec_info.codecType = kVideoCodecVP9;
103 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
104 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200105 codec_info.codecSpecific.VP9.temporal_idx = 2;
106 codec_info.codecSpecific.VP9.end_of_picture = false;
107
philipelbf2b6202018-08-27 14:33:18 +0200108 RTPVideoHeader header =
109 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200110
111 EXPECT_EQ(kVideoRotation_90, header.rotation);
112 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
113 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100114 EXPECT_FALSE(header.color_space);
philipel29d88462018-08-08 14:26:00 +0200115 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);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200120 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200121 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200122 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200123 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200124 codec_info.codecSpecific.VP9.end_of_picture);
125
126 // Next spatial layer.
127 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200128 codec_info.codecSpecific.VP9.end_of_picture = true;
129
Niels Möllerd3b8c632018-08-27 15:33:42 +0200130 encoded_image.SetSpatialIndex(1);
Johannes Krond0b69a82018-12-03 14:18:53 +0100131 ColorSpace color_space(
132 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
133 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
Danil Chapovalovb7698942019-02-05 11:32:19 +0100134 encoded_image.SetColorSpace(color_space);
philipelbf2b6202018-08-27 14:33:18 +0200135 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200136
137 EXPECT_EQ(kVideoRotation_90, header.rotation);
138 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
139 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100140 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
philipel29d88462018-08-08 14:26:00 +0200141 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);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200144 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200145 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200146 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200147 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200148 codec_info.codecSpecific.VP9.end_of_picture);
149}
150
151TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_H264) {
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500152 RtpPayloadState state;
153 state.picture_id = kPictureId;
154 state.tl0_pic_idx = kInitialTl0PicIdx1;
Erik Språngcbc0cba2020-04-18 14:36:59 +0200155 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Stefan Holmerf7044682018-07-17 10:16:41 +0200156
157 EncodedImage encoded_image;
158 CodecSpecificInfo codec_info;
Jonas Olssona4d87372019-07-05 19:08:33 +0200159 CodecSpecificInfoH264* h264info = &codec_info.codecSpecific.H264;
Stefan Holmerf7044682018-07-17 10:16:41 +0200160 codec_info.codecType = kVideoCodecH264;
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500161 h264info->packetization_mode = H264PacketizationMode::SingleNalUnit;
162 h264info->temporal_idx = kNoTemporalIdx;
Stefan Holmerf7044682018-07-17 10:16:41 +0200163
philipelbf2b6202018-08-27 14:33:18 +0200164 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100165 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
Stefan Holmerf7044682018-07-17 10:16:41 +0200166
167 EXPECT_EQ(0, header.simulcastIdx);
168 EXPECT_EQ(kVideoCodecH264, header.codec);
169 const auto& h264 = absl::get<RTPVideoHeaderH264>(header.video_type_header);
170 EXPECT_EQ(H264PacketizationMode::SingleNalUnit, h264.packetization_mode);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500171
172 // test temporal param 1
173 h264info->temporal_idx = 1;
174 h264info->base_layer_sync = true;
175 h264info->idr_frame = false;
176
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100177 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500178
179 EXPECT_EQ(kVideoCodecH264, header.codec);
180 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1);
181 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
182 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
183 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
184
185 // test temporal param 2
186 h264info->temporal_idx = 0;
187 h264info->base_layer_sync = false;
188 h264info->idr_frame = true;
189
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100190 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 30);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500191
192 EXPECT_EQ(kVideoCodecH264, header.codec);
193 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1 + 1);
194 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
195 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
196 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
Stefan Holmerf7044682018-07-17 10:16:41 +0200197}
198
199TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
200 RtpPayloadState state;
201 state.picture_id = kInitialPictureId1;
202 state.tl0_pic_idx = kInitialTl0PicIdx1;
203
204 EncodedImage encoded_image;
205 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200206 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200207
Erik Språngcbc0cba2020-04-18 14:36:59 +0200208 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200209 RTPVideoHeader header =
210 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200211 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000212 EXPECT_EQ(kInitialPictureId1 + 1,
213 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200214
215 // State should hold latest used picture id and tl0_pic_idx.
216 state = params.state();
217 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
218 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
219}
220
221TEST(RtpPayloadParamsTest, PictureIdWraps) {
222 RtpPayloadState state;
223 state.picture_id = kMaxTwoBytePictureId;
224 state.tl0_pic_idx = kInitialTl0PicIdx1;
225
226 EncodedImage encoded_image;
227 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200228 codec_info.codecType = kVideoCodecVP8;
229 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
230
Erik Språngcbc0cba2020-04-18 14:36:59 +0200231 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200232 RTPVideoHeader header =
233 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200234 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000235 EXPECT_EQ(0,
236 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200237
238 // State should hold latest used picture id and tl0_pic_idx.
239 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
240 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
241}
242
243TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
244 RtpPayloadState state;
245 state.picture_id = kInitialPictureId1;
246 state.tl0_pic_idx = kInitialTl0PicIdx1;
247
248 EncodedImage encoded_image;
249 // Modules are sending for this test.
250 // OnEncodedImage, temporalIdx: 1.
251 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200252 codec_info.codecType = kVideoCodecVP8;
253 codec_info.codecSpecific.VP8.temporalIdx = 1;
254
Erik Språngcbc0cba2020-04-18 14:36:59 +0200255 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200256 RTPVideoHeader header =
257 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200258
259 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000260 const auto& vp8_header =
261 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
262 EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
263 EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200264
265 // OnEncodedImage, temporalIdx: 0.
266 codec_info.codecSpecific.VP8.temporalIdx = 0;
267
philipelbf2b6202018-08-27 14:33:18 +0200268 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200269 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000270 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
271 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200272
273 // State should hold latest used picture id and tl0_pic_idx.
274 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
275 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
276}
277
278TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
279 RtpPayloadState state;
280 state.picture_id = kInitialPictureId1;
281 state.tl0_pic_idx = kInitialTl0PicIdx1;
282
283 EncodedImage encoded_image;
284 // Modules are sending for this test.
285 // OnEncodedImage, temporalIdx: 1.
286 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200287 codec_info.codecType = kVideoCodecVP9;
288 codec_info.codecSpecific.VP9.temporal_idx = 1;
289 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
290
Erik Språngcbc0cba2020-04-18 14:36:59 +0200291 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200292 RTPVideoHeader header =
293 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200294
295 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200296 const auto& vp9_header =
297 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
298 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
299 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200300
301 // OnEncodedImage, temporalIdx: 0.
302 codec_info.codecSpecific.VP9.temporal_idx = 0;
303
philipelbf2b6202018-08-27 14:33:18 +0200304 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200305
306 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200307 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
308 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200309
310 // OnEncodedImage, first_frame_in_picture = false
311 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
312
philipelbf2b6202018-08-27 14:33:18 +0200313 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200314
315 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200316 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
317 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200318
319 // State should hold latest used picture id and tl0_pic_idx.
320 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
321 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
322}
philipelbf2b6202018-08-27 14:33:18 +0200323
324TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
325 test::ScopedFieldTrials generic_picture_id(
326 "WebRTC-GenericPictureId/Enabled/");
327 RtpPayloadState state{};
328
329 EncodedImage encoded_image;
philipeld1d03592019-03-01 13:53:55 +0100330 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200331 codec_info.codecType = kVideoCodecGeneric;
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100332 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
philipelbf2b6202018-08-27 14:33:18 +0200333
Erik Språngcbc0cba2020-04-18 14:36:59 +0200334 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipelbf2b6202018-08-27 14:33:18 +0200335 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100336 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
philipelbf2b6202018-08-27 14:33:18 +0200337
338 EXPECT_EQ(kVideoCodecGeneric, header.codec);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100339 const auto* generic =
340 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
341 ASSERT_TRUE(generic);
342 EXPECT_EQ(0, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200343
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100344 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
345 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100346 generic =
347 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
348 ASSERT_TRUE(generic);
349 EXPECT_EQ(1, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200350}
351
philipel8aba8fe2019-06-13 15:13:16 +0200352TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
353 test::ScopedFieldTrials generic_picture_id(
354 "WebRTC-GenericDescriptor/Enabled/");
355 RtpPayloadState state{};
356
357 EncodedImage encoded_image;
358 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
359 CodecSpecificInfo codec_info;
360 codec_info.codecType = kVideoCodecGeneric;
361
Erik Språngcbc0cba2020-04-18 14:36:59 +0200362 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
philipel8aba8fe2019-06-13 15:13:16 +0200363 RTPVideoHeader header =
364 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
365
366 EXPECT_EQ(kVideoCodecGeneric, header.codec);
367 ASSERT_TRUE(header.generic);
368 EXPECT_EQ(0, header.generic->frame_id);
369 EXPECT_THAT(header.generic->dependencies, IsEmpty());
370
371 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
372 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
373 ASSERT_TRUE(header.generic);
374 EXPECT_EQ(1, header.generic->frame_id);
375 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
376}
377
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100378TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
379 test::ScopedFieldTrials generic_picture_id(
380 "WebRTC-GenericDescriptor/Enabled/");
381 RtpPayloadState state;
382 EncodedImage encoded_image;
383 CodecSpecificInfo codec_info;
384
Erik Språngcbc0cba2020-04-18 14:36:59 +0200385 RtpPayloadParams params(kSsrc1, &state, FieldTrialBasedConfig());
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100386
387 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
388 codec_info.generic_frame_info =
389 GenericFrameInfo::Builder().S(1).T(0).Dtis("S").Build();
390 codec_info.generic_frame_info->encoder_buffers = {
391 {/*id=*/0, /*referenced=*/false, /*updated=*/true}};
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200392 codec_info.generic_frame_info->part_of_chain = {true, false};
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100393 RTPVideoHeader key_header =
394 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/1);
395
396 ASSERT_TRUE(key_header.generic);
397 EXPECT_EQ(key_header.generic->spatial_index, 1);
398 EXPECT_EQ(key_header.generic->temporal_index, 0);
399 EXPECT_EQ(key_header.generic->frame_id, 1);
400 EXPECT_THAT(key_header.generic->dependencies, IsEmpty());
401 EXPECT_THAT(key_header.generic->decode_target_indications,
402 ElementsAre(DecodeTargetIndication::kSwitch));
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200403 EXPECT_THAT(key_header.generic->chain_diffs, SizeIs(2));
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100404
405 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
406 codec_info.generic_frame_info =
407 GenericFrameInfo::Builder().S(2).T(3).Dtis("D").Build();
408 codec_info.generic_frame_info->encoder_buffers = {
409 {/*id=*/0, /*referenced=*/true, /*updated=*/false}};
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200410 codec_info.generic_frame_info->part_of_chain = {false, false};
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100411 RTPVideoHeader delta_header =
412 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/3);
413
414 ASSERT_TRUE(delta_header.generic);
415 EXPECT_EQ(delta_header.generic->spatial_index, 2);
416 EXPECT_EQ(delta_header.generic->temporal_index, 3);
417 EXPECT_EQ(delta_header.generic->frame_id, 3);
418 EXPECT_THAT(delta_header.generic->dependencies, ElementsAre(1));
419 EXPECT_THAT(delta_header.generic->decode_target_indications,
420 ElementsAre(DecodeTargetIndication::kDiscardable));
Danil Chapovalov4b860c12020-05-19 14:48:19 +0200421 EXPECT_THAT(delta_header.generic->chain_diffs, SizeIs(2));
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100422}
423
philipelbf2b6202018-08-27 14:33:18 +0200424class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
425 public:
426 enum LayerSync { kNoSync, kSync };
427
philipel569397f2018-09-26 12:25:31 +0200428 RtpPayloadParamsVp8ToGenericTest()
429 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
430 state_(),
Erik Språngcbc0cba2020-04-18 14:36:59 +0200431 params_(123, &state_, trials_config_) {}
philipelbf2b6202018-08-27 14:33:18 +0200432
433 void ConvertAndCheck(int temporal_index,
434 int64_t shared_frame_id,
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000435 VideoFrameType frame_type,
philipelbf2b6202018-08-27 14:33:18 +0200436 LayerSync layer_sync,
philipelfab91292018-10-17 14:36:08 +0200437 const std::set<int64_t>& expected_deps,
438 uint16_t width = 0,
439 uint16_t height = 0) {
philipelbf2b6202018-08-27 14:33:18 +0200440 EncodedImage encoded_image;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000441 encoded_image._frameType = frame_type;
philipelfab91292018-10-17 14:36:08 +0200442 encoded_image._encodedWidth = width;
443 encoded_image._encodedHeight = height;
philipelbf2b6202018-08-27 14:33:18 +0200444
philipeld1d03592019-03-01 13:53:55 +0100445 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200446 codec_info.codecType = kVideoCodecVP8;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000447 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
448 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
philipelbf2b6202018-08-27 14:33:18 +0200449
450 RTPVideoHeader header =
451 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
452
453 ASSERT_TRUE(header.generic);
philipelbf2b6202018-08-27 14:33:18 +0200454 EXPECT_EQ(header.generic->spatial_index, 0);
455
456 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
457 EXPECT_EQ(header.generic->temporal_index, temporal_index);
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000458 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
459 header.generic->dependencies.end());
460 EXPECT_EQ(expected_deps, actual_deps);
philipelfab91292018-10-17 14:36:08 +0200461
462 EXPECT_EQ(header.width, width);
463 EXPECT_EQ(header.height, height);
philipelbf2b6202018-08-27 14:33:18 +0200464 }
465
466 protected:
philipel569397f2018-09-26 12:25:31 +0200467 test::ScopedFieldTrials generic_descriptor_field_trial_;
Erik Språngcbc0cba2020-04-18 14:36:59 +0200468 FieldTrialBasedConfig trials_config_;
philipelbf2b6202018-08-27 14:33:18 +0200469 RtpPayloadState state_;
470 RtpPayloadParams params_;
471};
472
473TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000474 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
475 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
476 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200477}
478
479TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000480 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200481
482 EncodedImage encoded_image;
Niels Möller8f7ce222019-03-21 15:43:58 +0100483 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipeld1d03592019-03-01 13:53:55 +0100484 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200485 codec_info.codecType = kVideoCodecVP8;
486 codec_info.codecSpecific.VP8.temporalIdx =
487 RtpGenericFrameDescriptor::kMaxTemporalLayers;
488 codec_info.codecSpecific.VP8.layerSync = false;
489
490 RTPVideoHeader header =
491 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
492 EXPECT_FALSE(header.generic);
493}
494
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000495TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
496 // 02120212 pattern
497 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
498 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
499 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
500 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
philipelbf2b6202018-08-27 14:33:18 +0200501
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000502 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
503 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
504 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
505 {4}); // layer sync
506 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
philipelbf2b6202018-08-27 14:33:18 +0200507}
508
509TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
510 // 0101 pattern
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000511 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
512 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
philipelbf2b6202018-08-27 14:33:18 +0200513
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000514 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
515 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
philipelbf2b6202018-08-27 14:33:18 +0200516
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000517 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
518 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
philipelbf2b6202018-08-27 14:33:18 +0200519}
520
philipel8aba8fe2019-06-13 15:13:16 +0200521class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
522 public:
523 enum LayerSync { kNoSync, kSync };
524
525 RtpPayloadParamsH264ToGenericTest()
526 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
527 state_(),
Erik Språngcbc0cba2020-04-18 14:36:59 +0200528 params_(123, &state_, trials_config_) {}
philipel8aba8fe2019-06-13 15:13:16 +0200529
530 void ConvertAndCheck(int temporal_index,
531 int64_t shared_frame_id,
532 VideoFrameType frame_type,
533 LayerSync layer_sync,
534 const std::set<int64_t>& expected_deps,
535 uint16_t width = 0,
536 uint16_t height = 0) {
537 EncodedImage encoded_image;
538 encoded_image._frameType = frame_type;
539 encoded_image._encodedWidth = width;
540 encoded_image._encodedHeight = height;
541
542 CodecSpecificInfo codec_info;
543 codec_info.codecType = kVideoCodecH264;
544 codec_info.codecSpecific.H264.temporal_idx = temporal_index;
545 codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
546
547 RTPVideoHeader header =
548 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
549
550 ASSERT_TRUE(header.generic);
philipel8aba8fe2019-06-13 15:13:16 +0200551 EXPECT_EQ(header.generic->spatial_index, 0);
552
553 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
554 EXPECT_EQ(header.generic->temporal_index, temporal_index);
555 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
556 header.generic->dependencies.end());
557 EXPECT_EQ(expected_deps, actual_deps);
558
559 EXPECT_EQ(header.width, width);
560 EXPECT_EQ(header.height, height);
561 }
562
563 protected:
564 test::ScopedFieldTrials generic_descriptor_field_trial_;
Erik Språngcbc0cba2020-04-18 14:36:59 +0200565 FieldTrialBasedConfig trials_config_;
philipel8aba8fe2019-06-13 15:13:16 +0200566 RtpPayloadState state_;
567 RtpPayloadParams params_;
568};
569
570TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
571 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
572 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
573 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
574}
575
576TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
577 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
578
579 EncodedImage encoded_image;
580 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
581 CodecSpecificInfo codec_info;
582 codec_info.codecType = kVideoCodecH264;
583 codec_info.codecSpecific.H264.temporal_idx =
584 RtpGenericFrameDescriptor::kMaxTemporalLayers;
585 codec_info.codecSpecific.H264.base_layer_sync = false;
586
587 RTPVideoHeader header =
588 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
589 EXPECT_FALSE(header.generic);
590}
591
592TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
593 // 02120212 pattern
594 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
595 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
596 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
597 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
598
599 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
600 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
601 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
602 {4}); // layer sync
603 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
604}
605
606TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
607 // 0101 pattern
608 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
609 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
610
611 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
612 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
613
614 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
615 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
616}
617
Stefan Holmerf7044682018-07-17 10:16:41 +0200618} // namespace webrtc