blob: 54b4025ceb99f0399102a2c76b2409b3252dc505 [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"
21#include "api/video/video_content_type.h"
22#include "api/video/video_rotation.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "modules/video_coding/codecs/h264/include/h264_globals.h"
24#include "modules/video_coding/codecs/interface/common_constants.h"
25#include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
26#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020027#include "modules/video_coding/include/video_codec_interface.h"
philipelbf2b6202018-08-27 14:33:18 +020028#include "test/field_trial.h"
philipel8aba8fe2019-06-13 15:13:16 +020029#include "test/gmock.h"
Stefan Holmerf7044682018-07-17 10:16:41 +020030#include "test/gtest.h"
31
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010032using ::testing::ElementsAre;
33using ::testing::IsEmpty;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010034
Qingsi Wang1c1b99e2020-01-07 19:16:33 +000035namespace webrtc {
36namespace {
Stefan Holmerf7044682018-07-17 10:16:41 +020037const uint32_t kSsrc1 = 12345;
38const uint32_t kSsrc2 = 23456;
39const int16_t kPictureId = 123;
40const int16_t kTl0PicIdx = 20;
41const uint8_t kTemporalIdx = 1;
42const int16_t kInitialPictureId1 = 222;
43const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020044const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020045} // namespace
46
47TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
48 RtpPayloadState state2;
49 state2.picture_id = kPictureId;
50 state2.tl0_pic_idx = kTl0PicIdx;
51 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
52
53 RtpPayloadParams params(kSsrc2, &state2);
54 EncodedImage encoded_image;
55 encoded_image.rotation_ = kVideoRotation_90;
56 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020057 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020058
59 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020060 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020061 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020062 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020063 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020064 codec_info.codecSpecific.VP8.nonReference = true;
65
philipelbf2b6202018-08-27 14:33:18 +020066 RTPVideoHeader header =
67 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
68
69 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020070 codec_info.codecSpecific.VP8.temporalIdx = 1;
71 codec_info.codecSpecific.VP8.layerSync = true;
72
73 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020074
75 EXPECT_EQ(kVideoRotation_90, header.rotation);
76 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
77 EXPECT_EQ(1, header.simulcastIdx);
78 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +000079 const auto& vp8_header =
80 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
81 EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
82 EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
83 EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
84 EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
85 EXPECT_TRUE(vp8_header.layerSync);
86 EXPECT_TRUE(vp8_header.nonReference);
Stefan Holmerf7044682018-07-17 10:16:41 +020087}
88
89TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
90 RtpPayloadState state;
91 state.picture_id = kPictureId;
92 state.tl0_pic_idx = kTl0PicIdx;
93 RtpPayloadParams params(kSsrc1, &state);
94
95 EncodedImage encoded_image;
96 encoded_image.rotation_ = kVideoRotation_90;
97 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020098 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +020099 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200100 codec_info.codecType = kVideoCodecVP9;
101 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
102 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200103 codec_info.codecSpecific.VP9.temporal_idx = 2;
104 codec_info.codecSpecific.VP9.end_of_picture = false;
105
philipelbf2b6202018-08-27 14:33:18 +0200106 RTPVideoHeader header =
107 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200108
109 EXPECT_EQ(kVideoRotation_90, header.rotation);
110 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
111 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100112 EXPECT_FALSE(header.color_space);
philipel29d88462018-08-08 14:26:00 +0200113 const auto& vp9_header =
114 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
115 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
116 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
117 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200118 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200119 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200120 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200121 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200122 codec_info.codecSpecific.VP9.end_of_picture);
123
124 // Next spatial layer.
125 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200126 codec_info.codecSpecific.VP9.end_of_picture = true;
127
Niels Möllerd3b8c632018-08-27 15:33:42 +0200128 encoded_image.SetSpatialIndex(1);
Johannes Krond0b69a82018-12-03 14:18:53 +0100129 ColorSpace color_space(
130 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
131 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
Danil Chapovalovb7698942019-02-05 11:32:19 +0100132 encoded_image.SetColorSpace(color_space);
philipelbf2b6202018-08-27 14:33:18 +0200133 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200134
135 EXPECT_EQ(kVideoRotation_90, header.rotation);
136 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
137 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100138 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
philipel29d88462018-08-08 14:26:00 +0200139 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
140 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
141 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200142 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200143 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200144 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200145 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200146 codec_info.codecSpecific.VP9.end_of_picture);
147}
148
149TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_H264) {
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500150 RtpPayloadState state;
151 state.picture_id = kPictureId;
152 state.tl0_pic_idx = kInitialTl0PicIdx1;
153 RtpPayloadParams params(kSsrc1, &state);
Stefan Holmerf7044682018-07-17 10:16:41 +0200154
155 EncodedImage encoded_image;
156 CodecSpecificInfo codec_info;
Jonas Olssona4d87372019-07-05 19:08:33 +0200157 CodecSpecificInfoH264* h264info = &codec_info.codecSpecific.H264;
Stefan Holmerf7044682018-07-17 10:16:41 +0200158 codec_info.codecType = kVideoCodecH264;
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500159 h264info->packetization_mode = H264PacketizationMode::SingleNalUnit;
160 h264info->temporal_idx = kNoTemporalIdx;
Stefan Holmerf7044682018-07-17 10:16:41 +0200161
philipelbf2b6202018-08-27 14:33:18 +0200162 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100163 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
Stefan Holmerf7044682018-07-17 10:16:41 +0200164
165 EXPECT_EQ(0, header.simulcastIdx);
166 EXPECT_EQ(kVideoCodecH264, header.codec);
167 const auto& h264 = absl::get<RTPVideoHeaderH264>(header.video_type_header);
168 EXPECT_EQ(H264PacketizationMode::SingleNalUnit, h264.packetization_mode);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500169
170 // test temporal param 1
171 h264info->temporal_idx = 1;
172 h264info->base_layer_sync = true;
173 h264info->idr_frame = false;
174
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100175 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500176
177 EXPECT_EQ(kVideoCodecH264, header.codec);
178 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1);
179 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
180 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
181 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
182
183 // test temporal param 2
184 h264info->temporal_idx = 0;
185 h264info->base_layer_sync = false;
186 h264info->idr_frame = true;
187
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100188 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 30);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500189
190 EXPECT_EQ(kVideoCodecH264, header.codec);
191 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1 + 1);
192 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
193 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
194 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
Stefan Holmerf7044682018-07-17 10:16:41 +0200195}
196
197TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
198 RtpPayloadState state;
199 state.picture_id = kInitialPictureId1;
200 state.tl0_pic_idx = kInitialTl0PicIdx1;
201
202 EncodedImage encoded_image;
203 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200204 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200205
206 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200207 RTPVideoHeader header =
208 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200209 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000210 EXPECT_EQ(kInitialPictureId1 + 1,
211 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200212
213 // State should hold latest used picture id and tl0_pic_idx.
214 state = params.state();
215 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
216 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
217}
218
219TEST(RtpPayloadParamsTest, PictureIdWraps) {
220 RtpPayloadState state;
221 state.picture_id = kMaxTwoBytePictureId;
222 state.tl0_pic_idx = kInitialTl0PicIdx1;
223
224 EncodedImage encoded_image;
225 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200226 codec_info.codecType = kVideoCodecVP8;
227 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
228
229 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200230 RTPVideoHeader header =
231 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200232 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000233 EXPECT_EQ(0,
234 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200235
236 // State should hold latest used picture id and tl0_pic_idx.
237 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
238 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
239}
240
241TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
242 RtpPayloadState state;
243 state.picture_id = kInitialPictureId1;
244 state.tl0_pic_idx = kInitialTl0PicIdx1;
245
246 EncodedImage encoded_image;
247 // Modules are sending for this test.
248 // OnEncodedImage, temporalIdx: 1.
249 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200250 codec_info.codecType = kVideoCodecVP8;
251 codec_info.codecSpecific.VP8.temporalIdx = 1;
252
253 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200254 RTPVideoHeader header =
255 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200256
257 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000258 const auto& vp8_header =
259 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
260 EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
261 EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200262
263 // OnEncodedImage, temporalIdx: 0.
264 codec_info.codecSpecific.VP8.temporalIdx = 0;
265
philipelbf2b6202018-08-27 14:33:18 +0200266 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200267 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000268 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
269 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200270
271 // State should hold latest used picture id and tl0_pic_idx.
272 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
273 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
274}
275
276TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
277 RtpPayloadState state;
278 state.picture_id = kInitialPictureId1;
279 state.tl0_pic_idx = kInitialTl0PicIdx1;
280
281 EncodedImage encoded_image;
282 // Modules are sending for this test.
283 // OnEncodedImage, temporalIdx: 1.
284 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200285 codec_info.codecType = kVideoCodecVP9;
286 codec_info.codecSpecific.VP9.temporal_idx = 1;
287 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
288
289 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200290 RTPVideoHeader header =
291 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200292
293 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200294 const auto& vp9_header =
295 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
296 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
297 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200298
299 // OnEncodedImage, temporalIdx: 0.
300 codec_info.codecSpecific.VP9.temporal_idx = 0;
301
philipelbf2b6202018-08-27 14:33:18 +0200302 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200303
304 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200305 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
306 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200307
308 // OnEncodedImage, first_frame_in_picture = false
309 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
310
philipelbf2b6202018-08-27 14:33:18 +0200311 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200312
313 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200314 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
315 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200316
317 // State should hold latest used picture id and tl0_pic_idx.
318 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
319 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
320}
philipelbf2b6202018-08-27 14:33:18 +0200321
322TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
323 test::ScopedFieldTrials generic_picture_id(
324 "WebRTC-GenericPictureId/Enabled/");
325 RtpPayloadState state{};
326
327 EncodedImage encoded_image;
philipeld1d03592019-03-01 13:53:55 +0100328 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200329 codec_info.codecType = kVideoCodecGeneric;
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100330 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
philipelbf2b6202018-08-27 14:33:18 +0200331
332 RtpPayloadParams params(kSsrc1, &state);
333 RTPVideoHeader header =
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100334 params.GetRtpVideoHeader(encoded_image, &codec_info, 10);
philipelbf2b6202018-08-27 14:33:18 +0200335
336 EXPECT_EQ(kVideoCodecGeneric, header.codec);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100337 const auto* generic =
338 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
339 ASSERT_TRUE(generic);
340 EXPECT_EQ(0, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200341
Markus Handellc1cbf6b2020-02-17 20:03:57 +0100342 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
343 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 20);
Danil Chapovalovb6bf0b22020-01-28 18:36:57 +0100344 generic =
345 absl::get_if<RTPVideoHeaderLegacyGeneric>(&header.video_type_header);
346 ASSERT_TRUE(generic);
347 EXPECT_EQ(1, generic->picture_id);
philipelbf2b6202018-08-27 14:33:18 +0200348}
349
philipel8aba8fe2019-06-13 15:13:16 +0200350TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
351 test::ScopedFieldTrials generic_picture_id(
352 "WebRTC-GenericDescriptor/Enabled/");
353 RtpPayloadState state{};
354
355 EncodedImage encoded_image;
356 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
357 CodecSpecificInfo codec_info;
358 codec_info.codecType = kVideoCodecGeneric;
359
360 RtpPayloadParams params(kSsrc1, &state);
361 RTPVideoHeader header =
362 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
363
364 EXPECT_EQ(kVideoCodecGeneric, header.codec);
365 ASSERT_TRUE(header.generic);
366 EXPECT_EQ(0, header.generic->frame_id);
367 EXPECT_THAT(header.generic->dependencies, IsEmpty());
368
369 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
370 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
371 ASSERT_TRUE(header.generic);
372 EXPECT_EQ(1, header.generic->frame_id);
373 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
374}
375
Danil Chapovalov02d71fb2020-02-10 16:22:57 +0100376TEST(RtpPayloadParamsTest, SetsGenericFromGenericFrameInfo) {
377 test::ScopedFieldTrials generic_picture_id(
378 "WebRTC-GenericDescriptor/Enabled/");
379 RtpPayloadState state;
380 EncodedImage encoded_image;
381 CodecSpecificInfo codec_info;
382
383 RtpPayloadParams params(kSsrc1, &state);
384
385 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
386 codec_info.generic_frame_info =
387 GenericFrameInfo::Builder().S(1).T(0).Dtis("S").Build();
388 codec_info.generic_frame_info->encoder_buffers = {
389 {/*id=*/0, /*referenced=*/false, /*updated=*/true}};
390 RTPVideoHeader key_header =
391 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/1);
392
393 ASSERT_TRUE(key_header.generic);
394 EXPECT_EQ(key_header.generic->spatial_index, 1);
395 EXPECT_EQ(key_header.generic->temporal_index, 0);
396 EXPECT_EQ(key_header.generic->frame_id, 1);
397 EXPECT_THAT(key_header.generic->dependencies, IsEmpty());
398 EXPECT_THAT(key_header.generic->decode_target_indications,
399 ElementsAre(DecodeTargetIndication::kSwitch));
400 EXPECT_FALSE(key_header.generic->discardable);
401
402 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
403 codec_info.generic_frame_info =
404 GenericFrameInfo::Builder().S(2).T(3).Dtis("D").Build();
405 codec_info.generic_frame_info->encoder_buffers = {
406 {/*id=*/0, /*referenced=*/true, /*updated=*/false}};
407 RTPVideoHeader delta_header =
408 params.GetRtpVideoHeader(encoded_image, &codec_info, /*frame_id=*/3);
409
410 ASSERT_TRUE(delta_header.generic);
411 EXPECT_EQ(delta_header.generic->spatial_index, 2);
412 EXPECT_EQ(delta_header.generic->temporal_index, 3);
413 EXPECT_EQ(delta_header.generic->frame_id, 3);
414 EXPECT_THAT(delta_header.generic->dependencies, ElementsAre(1));
415 EXPECT_THAT(delta_header.generic->decode_target_indications,
416 ElementsAre(DecodeTargetIndication::kDiscardable));
417 EXPECT_TRUE(delta_header.generic->discardable);
418}
419
philipelbf2b6202018-08-27 14:33:18 +0200420class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
421 public:
422 enum LayerSync { kNoSync, kSync };
423
philipel569397f2018-09-26 12:25:31 +0200424 RtpPayloadParamsVp8ToGenericTest()
425 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
426 state_(),
427 params_(123, &state_) {}
philipelbf2b6202018-08-27 14:33:18 +0200428
429 void ConvertAndCheck(int temporal_index,
430 int64_t shared_frame_id,
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000431 VideoFrameType frame_type,
philipelbf2b6202018-08-27 14:33:18 +0200432 LayerSync layer_sync,
philipelfab91292018-10-17 14:36:08 +0200433 const std::set<int64_t>& expected_deps,
434 uint16_t width = 0,
435 uint16_t height = 0) {
philipelbf2b6202018-08-27 14:33:18 +0200436 EncodedImage encoded_image;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000437 encoded_image._frameType = frame_type;
philipelfab91292018-10-17 14:36:08 +0200438 encoded_image._encodedWidth = width;
439 encoded_image._encodedHeight = height;
philipelbf2b6202018-08-27 14:33:18 +0200440
philipeld1d03592019-03-01 13:53:55 +0100441 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200442 codec_info.codecType = kVideoCodecVP8;
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000443 codec_info.codecSpecific.VP8.temporalIdx = temporal_index;
444 codec_info.codecSpecific.VP8.layerSync = layer_sync == kSync;
philipelbf2b6202018-08-27 14:33:18 +0200445
446 RTPVideoHeader header =
447 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
448
449 ASSERT_TRUE(header.generic);
philipelbf2b6202018-08-27 14:33:18 +0200450 EXPECT_EQ(header.generic->spatial_index, 0);
451
452 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
453 EXPECT_EQ(header.generic->temporal_index, temporal_index);
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000454 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
455 header.generic->dependencies.end());
456 EXPECT_EQ(expected_deps, actual_deps);
philipelfab91292018-10-17 14:36:08 +0200457
458 EXPECT_EQ(header.width, width);
459 EXPECT_EQ(header.height, height);
philipelbf2b6202018-08-27 14:33:18 +0200460 }
461
462 protected:
philipel569397f2018-09-26 12:25:31 +0200463 test::ScopedFieldTrials generic_descriptor_field_trial_;
philipelbf2b6202018-08-27 14:33:18 +0200464 RtpPayloadState state_;
465 RtpPayloadParams params_;
466};
467
468TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000469 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
470 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
471 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200472}
473
474TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000475 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
philipelbf2b6202018-08-27 14:33:18 +0200476
477 EncodedImage encoded_image;
Niels Möller8f7ce222019-03-21 15:43:58 +0100478 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipeld1d03592019-03-01 13:53:55 +0100479 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200480 codec_info.codecType = kVideoCodecVP8;
481 codec_info.codecSpecific.VP8.temporalIdx =
482 RtpGenericFrameDescriptor::kMaxTemporalLayers;
483 codec_info.codecSpecific.VP8.layerSync = false;
484
485 RTPVideoHeader header =
486 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
487 EXPECT_FALSE(header.generic);
488}
489
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000490TEST_F(RtpPayloadParamsVp8ToGenericTest, LayerSync) {
491 // 02120212 pattern
492 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
493 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
494 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
495 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
philipelbf2b6202018-08-27 14:33:18 +0200496
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000497 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
498 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
499 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
500 {4}); // layer sync
501 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
philipelbf2b6202018-08-27 14:33:18 +0200502}
503
504TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
505 // 0101 pattern
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000506 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
507 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
philipelbf2b6202018-08-27 14:33:18 +0200508
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000509 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
510 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
philipelbf2b6202018-08-27 14:33:18 +0200511
Qingsi Wang1c1b99e2020-01-07 19:16:33 +0000512 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
513 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
philipelbf2b6202018-08-27 14:33:18 +0200514}
515
philipel8aba8fe2019-06-13 15:13:16 +0200516class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
517 public:
518 enum LayerSync { kNoSync, kSync };
519
520 RtpPayloadParamsH264ToGenericTest()
521 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
522 state_(),
523 params_(123, &state_) {}
524
525 void ConvertAndCheck(int temporal_index,
526 int64_t shared_frame_id,
527 VideoFrameType frame_type,
528 LayerSync layer_sync,
529 const std::set<int64_t>& expected_deps,
530 uint16_t width = 0,
531 uint16_t height = 0) {
532 EncodedImage encoded_image;
533 encoded_image._frameType = frame_type;
534 encoded_image._encodedWidth = width;
535 encoded_image._encodedHeight = height;
536
537 CodecSpecificInfo codec_info;
538 codec_info.codecType = kVideoCodecH264;
539 codec_info.codecSpecific.H264.temporal_idx = temporal_index;
540 codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
541
542 RTPVideoHeader header =
543 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
544
545 ASSERT_TRUE(header.generic);
philipel8aba8fe2019-06-13 15:13:16 +0200546 EXPECT_EQ(header.generic->spatial_index, 0);
547
548 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
549 EXPECT_EQ(header.generic->temporal_index, temporal_index);
550 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
551 header.generic->dependencies.end());
552 EXPECT_EQ(expected_deps, actual_deps);
553
554 EXPECT_EQ(header.width, width);
555 EXPECT_EQ(header.height, height);
556 }
557
558 protected:
559 test::ScopedFieldTrials generic_descriptor_field_trial_;
560 RtpPayloadState state_;
561 RtpPayloadParams params_;
562};
563
564TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
565 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
566 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
567 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
568}
569
570TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
571 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
572
573 EncodedImage encoded_image;
574 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
575 CodecSpecificInfo codec_info;
576 codec_info.codecType = kVideoCodecH264;
577 codec_info.codecSpecific.H264.temporal_idx =
578 RtpGenericFrameDescriptor::kMaxTemporalLayers;
579 codec_info.codecSpecific.H264.base_layer_sync = false;
580
581 RTPVideoHeader header =
582 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
583 EXPECT_FALSE(header.generic);
584}
585
586TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
587 // 02120212 pattern
588 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
589 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
590 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
591 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
592
593 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
594 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
595 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
596 {4}); // layer sync
597 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
598}
599
600TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
601 // 0101 pattern
602 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
603 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
604
605 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
606 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
607
608 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
609 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
610}
611
Stefan Holmerf7044682018-07-17 10:16:41 +0200612} // namespace webrtc