blob: 2438f769fff3fc7e6ae933aacafe503280e1a404 [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>
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010017#include <vector>
Stefan Holmerf7044682018-07-17 10:16:41 +020018
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "absl/container/inlined_vector.h"
20#include "absl/types/optional.h"
21#include "absl/types/variant.h"
22#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
33namespace webrtc {
34namespace {
Danil Chapovalovdc7fe402019-12-13 12:23:58 +010035
36using ::testing::ElementsAre;
37using ::testing::IsEmpty;
38using ::testing::UnorderedElementsAreArray;
39
Stefan Holmerf7044682018-07-17 10:16:41 +020040const uint32_t kSsrc1 = 12345;
41const uint32_t kSsrc2 = 23456;
42const int16_t kPictureId = 123;
43const int16_t kTl0PicIdx = 20;
44const uint8_t kTemporalIdx = 1;
45const int16_t kInitialPictureId1 = 222;
46const int16_t kInitialTl0PicIdx1 = 99;
philipelbf2b6202018-08-27 14:33:18 +020047const int64_t kDontCare = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020048} // namespace
49
50TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp8) {
51 RtpPayloadState state2;
52 state2.picture_id = kPictureId;
53 state2.tl0_pic_idx = kTl0PicIdx;
54 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
55
56 RtpPayloadParams params(kSsrc2, &state2);
57 EncodedImage encoded_image;
58 encoded_image.rotation_ = kVideoRotation_90;
59 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +020060 encoded_image.SetSpatialIndex(1);
Stefan Holmerf7044682018-07-17 10:16:41 +020061
62 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +020063 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020064 codec_info.codecSpecific.VP8.temporalIdx = 0;
Stefan Holmerf7044682018-07-17 10:16:41 +020065 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
philipelbf2b6202018-08-27 14:33:18 +020066 codec_info.codecSpecific.VP8.layerSync = false;
Stefan Holmerf7044682018-07-17 10:16:41 +020067 codec_info.codecSpecific.VP8.nonReference = true;
68
philipelbf2b6202018-08-27 14:33:18 +020069 RTPVideoHeader header =
70 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
71
72 codec_info.codecType = kVideoCodecVP8;
philipelbf2b6202018-08-27 14:33:18 +020073 codec_info.codecSpecific.VP8.temporalIdx = 1;
74 codec_info.codecSpecific.VP8.layerSync = true;
75
76 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
Stefan Holmerf7044682018-07-17 10:16:41 +020077
78 EXPECT_EQ(kVideoRotation_90, header.rotation);
79 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
80 EXPECT_EQ(1, header.simulcastIdx);
81 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +000082 const auto& vp8_header =
83 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
84 EXPECT_EQ(kPictureId + 2, vp8_header.pictureId);
85 EXPECT_EQ(kTemporalIdx, vp8_header.temporalIdx);
86 EXPECT_EQ(kTl0PicIdx + 1, vp8_header.tl0PicIdx);
87 EXPECT_EQ(kNoKeyIdx, vp8_header.keyIdx);
88 EXPECT_TRUE(vp8_header.layerSync);
89 EXPECT_TRUE(vp8_header.nonReference);
Stefan Holmerf7044682018-07-17 10:16:41 +020090}
91
92TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_Vp9) {
93 RtpPayloadState state;
94 state.picture_id = kPictureId;
95 state.tl0_pic_idx = kTl0PicIdx;
96 RtpPayloadParams params(kSsrc1, &state);
97
98 EncodedImage encoded_image;
99 encoded_image.rotation_ = kVideoRotation_90;
100 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200101 encoded_image.SetSpatialIndex(0);
Stefan Holmerf7044682018-07-17 10:16:41 +0200102 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200103 codec_info.codecType = kVideoCodecVP9;
104 codec_info.codecSpecific.VP9.num_spatial_layers = 3;
105 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Stefan Holmerf7044682018-07-17 10:16:41 +0200106 codec_info.codecSpecific.VP9.temporal_idx = 2;
107 codec_info.codecSpecific.VP9.end_of_picture = false;
108
philipelbf2b6202018-08-27 14:33:18 +0200109 RTPVideoHeader header =
110 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200111
112 EXPECT_EQ(kVideoRotation_90, header.rotation);
113 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
114 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100115 EXPECT_FALSE(header.color_space);
philipel29d88462018-08-08 14:26:00 +0200116 const auto& vp9_header =
117 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
118 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
119 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
120 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200121 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200122 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200123 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200124 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200125 codec_info.codecSpecific.VP9.end_of_picture);
126
127 // Next spatial layer.
128 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
Stefan Holmerf7044682018-07-17 10:16:41 +0200129 codec_info.codecSpecific.VP9.end_of_picture = true;
130
Niels Möllerd3b8c632018-08-27 15:33:42 +0200131 encoded_image.SetSpatialIndex(1);
Johannes Krond0b69a82018-12-03 14:18:53 +0100132 ColorSpace color_space(
133 ColorSpace::PrimaryID::kSMPTE170M, ColorSpace::TransferID::kSMPTE170M,
134 ColorSpace::MatrixID::kSMPTE170M, ColorSpace::RangeID::kFull);
Danil Chapovalovb7698942019-02-05 11:32:19 +0100135 encoded_image.SetColorSpace(color_space);
philipelbf2b6202018-08-27 14:33:18 +0200136 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200137
138 EXPECT_EQ(kVideoRotation_90, header.rotation);
139 EXPECT_EQ(VideoContentType::SCREENSHARE, header.content_type);
140 EXPECT_EQ(kVideoCodecVP9, header.codec);
Johannes Krond0b69a82018-12-03 14:18:53 +0100141 EXPECT_EQ(absl::make_optional(color_space), header.color_space);
philipel29d88462018-08-08 14:26:00 +0200142 EXPECT_EQ(kPictureId + 1, vp9_header.picture_id);
143 EXPECT_EQ(kTl0PicIdx, vp9_header.tl0_pic_idx);
144 EXPECT_EQ(vp9_header.temporal_idx, codec_info.codecSpecific.VP9.temporal_idx);
Niels Möllerd3b8c632018-08-27 15:33:42 +0200145 EXPECT_EQ(vp9_header.spatial_idx, encoded_image.SpatialIndex());
philipel29d88462018-08-08 14:26:00 +0200146 EXPECT_EQ(vp9_header.num_spatial_layers,
Stefan Holmerf7044682018-07-17 10:16:41 +0200147 codec_info.codecSpecific.VP9.num_spatial_layers);
philipel29d88462018-08-08 14:26:00 +0200148 EXPECT_EQ(vp9_header.end_of_picture,
Stefan Holmerf7044682018-07-17 10:16:41 +0200149 codec_info.codecSpecific.VP9.end_of_picture);
150}
151
152TEST(RtpPayloadParamsTest, InfoMappedToRtpVideoHeader_H264) {
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500153 RtpPayloadState state;
154 state.picture_id = kPictureId;
155 state.tl0_pic_idx = kInitialTl0PicIdx1;
156 RtpPayloadParams params(kSsrc1, &state);
Stefan Holmerf7044682018-07-17 10:16:41 +0200157
158 EncodedImage encoded_image;
159 CodecSpecificInfo codec_info;
Jonas Olssona4d87372019-07-05 19:08:33 +0200160 CodecSpecificInfoH264* h264info = &codec_info.codecSpecific.H264;
Stefan Holmerf7044682018-07-17 10:16:41 +0200161 codec_info.codecType = kVideoCodecH264;
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500162 h264info->packetization_mode = H264PacketizationMode::SingleNalUnit;
163 h264info->temporal_idx = kNoTemporalIdx;
Stefan Holmerf7044682018-07-17 10:16:41 +0200164
philipelbf2b6202018-08-27 14:33:18 +0200165 RTPVideoHeader header =
166 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200167
168 EXPECT_EQ(0, header.simulcastIdx);
169 EXPECT_EQ(kVideoCodecH264, header.codec);
170 const auto& h264 = absl::get<RTPVideoHeaderH264>(header.video_type_header);
171 EXPECT_EQ(H264PacketizationMode::SingleNalUnit, h264.packetization_mode);
Johnny Lee1a1c52b2019-02-08 14:25:40 -0500172
173 // test temporal param 1
174 h264info->temporal_idx = 1;
175 h264info->base_layer_sync = true;
176 h264info->idr_frame = false;
177
178 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
179
180 EXPECT_EQ(kVideoCodecH264, header.codec);
181 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1);
182 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
183 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
184 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
185
186 // test temporal param 2
187 h264info->temporal_idx = 0;
188 h264info->base_layer_sync = false;
189 h264info->idr_frame = true;
190
191 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
192
193 EXPECT_EQ(kVideoCodecH264, header.codec);
194 EXPECT_EQ(header.frame_marking.tl0_pic_idx, kInitialTl0PicIdx1 + 1);
195 EXPECT_EQ(header.frame_marking.temporal_id, h264info->temporal_idx);
196 EXPECT_EQ(header.frame_marking.base_layer_sync, h264info->base_layer_sync);
197 EXPECT_EQ(header.frame_marking.independent_frame, h264info->idr_frame);
Stefan Holmerf7044682018-07-17 10:16:41 +0200198}
199
200TEST(RtpPayloadParamsTest, PictureIdIsSetForVp8) {
201 RtpPayloadState state;
202 state.picture_id = kInitialPictureId1;
203 state.tl0_pic_idx = kInitialTl0PicIdx1;
204
205 EncodedImage encoded_image;
206 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200207 codec_info.codecType = kVideoCodecVP8;
Stefan Holmerf7044682018-07-17 10:16:41 +0200208
209 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200210 RTPVideoHeader header =
211 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200212 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000213 EXPECT_EQ(kInitialPictureId1 + 1,
214 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200215
216 // State should hold latest used picture id and tl0_pic_idx.
217 state = params.state();
218 EXPECT_EQ(kInitialPictureId1 + 1, state.picture_id);
219 EXPECT_EQ(kInitialTl0PicIdx1 + 1, state.tl0_pic_idx);
220}
221
222TEST(RtpPayloadParamsTest, PictureIdWraps) {
223 RtpPayloadState state;
224 state.picture_id = kMaxTwoBytePictureId;
225 state.tl0_pic_idx = kInitialTl0PicIdx1;
226
227 EncodedImage encoded_image;
228 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200229 codec_info.codecType = kVideoCodecVP8;
230 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
231
232 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200233 RTPVideoHeader header =
234 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200235 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000236 EXPECT_EQ(0,
237 absl::get<RTPVideoHeaderVP8>(header.video_type_header).pictureId);
Stefan Holmerf7044682018-07-17 10:16:41 +0200238
239 // State should hold latest used picture id and tl0_pic_idx.
240 EXPECT_EQ(0, params.state().picture_id); // Wrapped.
241 EXPECT_EQ(kInitialTl0PicIdx1, params.state().tl0_pic_idx);
242}
243
244TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp8) {
245 RtpPayloadState state;
246 state.picture_id = kInitialPictureId1;
247 state.tl0_pic_idx = kInitialTl0PicIdx1;
248
249 EncodedImage encoded_image;
250 // Modules are sending for this test.
251 // OnEncodedImage, temporalIdx: 1.
252 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200253 codec_info.codecType = kVideoCodecVP8;
254 codec_info.codecSpecific.VP8.temporalIdx = 1;
255
256 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200257 RTPVideoHeader header =
258 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200259
260 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000261 const auto& vp8_header =
262 absl::get<RTPVideoHeaderVP8>(header.video_type_header);
263 EXPECT_EQ(kInitialPictureId1 + 1, vp8_header.pictureId);
264 EXPECT_EQ(kInitialTl0PicIdx1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200265
266 // OnEncodedImage, temporalIdx: 0.
267 codec_info.codecSpecific.VP8.temporalIdx = 0;
268
philipelbf2b6202018-08-27 14:33:18 +0200269 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200270 EXPECT_EQ(kVideoCodecVP8, header.codec);
Philip Eliassond52a1a62018-09-07 13:03:55 +0000271 EXPECT_EQ(kInitialPictureId1 + 2, vp8_header.pictureId);
272 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp8_header.tl0PicIdx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200273
274 // State should hold latest used picture id and tl0_pic_idx.
275 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
276 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
277}
278
279TEST(RtpPayloadParamsTest, Tl0PicIdxUpdatedForVp9) {
280 RtpPayloadState state;
281 state.picture_id = kInitialPictureId1;
282 state.tl0_pic_idx = kInitialTl0PicIdx1;
283
284 EncodedImage encoded_image;
285 // Modules are sending for this test.
286 // OnEncodedImage, temporalIdx: 1.
287 CodecSpecificInfo codec_info;
Stefan Holmerf7044682018-07-17 10:16:41 +0200288 codec_info.codecType = kVideoCodecVP9;
289 codec_info.codecSpecific.VP9.temporal_idx = 1;
290 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
291
292 RtpPayloadParams params(kSsrc1, &state);
philipelbf2b6202018-08-27 14:33:18 +0200293 RTPVideoHeader header =
294 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200295
296 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200297 const auto& vp9_header =
298 absl::get<RTPVideoHeaderVP9>(header.video_type_header);
299 EXPECT_EQ(kInitialPictureId1 + 1, vp9_header.picture_id);
300 EXPECT_EQ(kInitialTl0PicIdx1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200301
302 // OnEncodedImage, temporalIdx: 0.
303 codec_info.codecSpecific.VP9.temporal_idx = 0;
304
philipelbf2b6202018-08-27 14:33:18 +0200305 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200306
307 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200308 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
309 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200310
311 // OnEncodedImage, first_frame_in_picture = false
312 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
313
philipelbf2b6202018-08-27 14:33:18 +0200314 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
Stefan Holmerf7044682018-07-17 10:16:41 +0200315
316 EXPECT_EQ(kVideoCodecVP9, header.codec);
philipel29d88462018-08-08 14:26:00 +0200317 EXPECT_EQ(kInitialPictureId1 + 2, vp9_header.picture_id);
318 EXPECT_EQ(kInitialTl0PicIdx1 + 1, vp9_header.tl0_pic_idx);
Stefan Holmerf7044682018-07-17 10:16:41 +0200319
320 // State should hold latest used picture id and tl0_pic_idx.
321 EXPECT_EQ(kInitialPictureId1 + 2, params.state().picture_id);
322 EXPECT_EQ(kInitialTl0PicIdx1 + 1, params.state().tl0_pic_idx);
323}
philipelbf2b6202018-08-27 14:33:18 +0200324
325TEST(RtpPayloadParamsTest, PictureIdForOldGenericFormat) {
326 test::ScopedFieldTrials generic_picture_id(
327 "WebRTC-GenericPictureId/Enabled/");
328 RtpPayloadState state{};
329
330 EncodedImage encoded_image;
philipeld1d03592019-03-01 13:53:55 +0100331 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200332 codec_info.codecType = kVideoCodecGeneric;
333
334 RtpPayloadParams params(kSsrc1, &state);
335 RTPVideoHeader header =
336 params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
337
338 EXPECT_EQ(kVideoCodecGeneric, header.codec);
339 ASSERT_TRUE(header.generic);
340 EXPECT_EQ(0, header.generic->frame_id);
341
342 header = params.GetRtpVideoHeader(encoded_image, &codec_info, kDontCare);
343 ASSERT_TRUE(header.generic);
344 EXPECT_EQ(1, header.generic->frame_id);
345}
346
philipel8aba8fe2019-06-13 15:13:16 +0200347TEST(RtpPayloadParamsTest, GenericDescriptorForGenericCodec) {
348 test::ScopedFieldTrials generic_picture_id(
349 "WebRTC-GenericDescriptor/Enabled/");
350 RtpPayloadState state{};
351
352 EncodedImage encoded_image;
353 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
354 CodecSpecificInfo codec_info;
355 codec_info.codecType = kVideoCodecGeneric;
356
357 RtpPayloadParams params(kSsrc1, &state);
358 RTPVideoHeader header =
359 params.GetRtpVideoHeader(encoded_image, &codec_info, 0);
360
361 EXPECT_EQ(kVideoCodecGeneric, header.codec);
362 ASSERT_TRUE(header.generic);
363 EXPECT_EQ(0, header.generic->frame_id);
364 EXPECT_THAT(header.generic->dependencies, IsEmpty());
365
366 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
367 header = params.GetRtpVideoHeader(encoded_image, &codec_info, 1);
368 ASSERT_TRUE(header.generic);
369 EXPECT_EQ(1, header.generic->frame_id);
370 EXPECT_THAT(header.generic->dependencies, ElementsAre(0));
371}
372
philipelbf2b6202018-08-27 14:33:18 +0200373class RtpPayloadParamsVp8ToGenericTest : public ::testing::Test {
374 public:
375 enum LayerSync { kNoSync, kSync };
376
philipel569397f2018-09-26 12:25:31 +0200377 RtpPayloadParamsVp8ToGenericTest()
378 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
379 state_(),
380 params_(123, &state_) {}
philipelbf2b6202018-08-27 14:33:18 +0200381
382 void ConvertAndCheck(int temporal_index,
383 int64_t shared_frame_id,
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100384 const std::vector<int>& references,
385 const std::vector<int>& updates,
philipelbf2b6202018-08-27 14:33:18 +0200386 LayerSync layer_sync,
philipelfab91292018-10-17 14:36:08 +0200387 const std::set<int64_t>& expected_deps,
388 uint16_t width = 0,
389 uint16_t height = 0) {
philipelbf2b6202018-08-27 14:33:18 +0200390 EncodedImage encoded_image;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100391 encoded_image._frameType = references.empty()
392 ? VideoFrameType::kVideoFrameKey
393 : VideoFrameType::kVideoFrameDelta;
philipelfab91292018-10-17 14:36:08 +0200394 encoded_image._encodedWidth = width;
395 encoded_image._encodedHeight = height;
philipelbf2b6202018-08-27 14:33:18 +0200396
philipeld1d03592019-03-01 13:53:55 +0100397 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200398 codec_info.codecType = kVideoCodecVP8;
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100399 auto& vp8 = codec_info.codecSpecific.VP8;
400 vp8.temporalIdx = temporal_index;
401 vp8.layerSync = layer_sync == kSync;
402 vp8.referencedBuffersCount = 0;
403 for (int reference : references) {
404 vp8.referencedBuffers[vp8.referencedBuffersCount++] = reference;
405 }
406 vp8.updatedBuffersCount = 0;
407 for (int update : updates) {
408 vp8.updatedBuffers[vp8.updatedBuffersCount++] = update;
409 }
philipelbf2b6202018-08-27 14:33:18 +0200410
411 RTPVideoHeader header =
412 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
413
414 ASSERT_TRUE(header.generic);
415 EXPECT_TRUE(header.generic->higher_spatial_layers.empty());
416 EXPECT_EQ(header.generic->spatial_index, 0);
417
418 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
419 EXPECT_EQ(header.generic->temporal_index, temporal_index);
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100420 EXPECT_THAT(header.generic->dependencies,
421 UnorderedElementsAreArray(expected_deps));
philipelfab91292018-10-17 14:36:08 +0200422
423 EXPECT_EQ(header.width, width);
424 EXPECT_EQ(header.height, height);
philipelbf2b6202018-08-27 14:33:18 +0200425 }
426
427 protected:
philipel569397f2018-09-26 12:25:31 +0200428 test::ScopedFieldTrials generic_descriptor_field_trial_;
philipelbf2b6202018-08-27 14:33:18 +0200429 RtpPayloadState state_;
430 RtpPayloadParams params_;
431};
432
433TEST_F(RtpPayloadParamsVp8ToGenericTest, Keyframe) {
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100434 ConvertAndCheck(0, 0, /*references=*/{}, /*updates=*/{0}, kNoSync, {}, 480,
435 360);
436 ConvertAndCheck(0, 1, /*references=*/{0}, /*updates=*/{0}, kNoSync, {0});
437 ConvertAndCheck(0, 2, /*references=*/{}, /*updates=*/{0}, kNoSync, {}, 480,
438 360);
philipelbf2b6202018-08-27 14:33:18 +0200439}
440
441TEST_F(RtpPayloadParamsVp8ToGenericTest, TooHighTemporalIndex) {
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100442 ConvertAndCheck(0, 0, /*references=*/{}, /*updates=*/{0}, kNoSync, {}, 480,
443 360);
philipelbf2b6202018-08-27 14:33:18 +0200444
445 EncodedImage encoded_image;
Niels Möller8f7ce222019-03-21 15:43:58 +0100446 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
philipeld1d03592019-03-01 13:53:55 +0100447 CodecSpecificInfo codec_info;
philipelbf2b6202018-08-27 14:33:18 +0200448 codec_info.codecType = kVideoCodecVP8;
449 codec_info.codecSpecific.VP8.temporalIdx =
450 RtpGenericFrameDescriptor::kMaxTemporalLayers;
451 codec_info.codecSpecific.VP8.layerSync = false;
452
453 RTPVideoHeader header =
454 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
455 EXPECT_FALSE(header.generic);
456}
457
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100458TEST_F(RtpPayloadParamsVp8ToGenericTest, Pattern02120212) {
459 ConvertAndCheck(0, 0, /*references=*/{}, /*updates=*/{0}, kNoSync, {}, 480,
460 360);
461 ConvertAndCheck(2, 1, /*references=*/{0}, /*updates=*/{2}, kNoSync, {0});
462 ConvertAndCheck(1, 2, /*references=*/{0}, /*updates=*/{1}, kNoSync, {0});
463 ConvertAndCheck(2, 3, /*references=*/{0, 1, 2}, /*updates=*/{2}, kNoSync,
464 {0, 1, 2});
philipelbf2b6202018-08-27 14:33:18 +0200465
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100466 ConvertAndCheck(0, 4, /*references=*/{0}, /*updates=*/{0}, kNoSync, {0});
467 ConvertAndCheck(2, 5, /*references=*/{0, 1, 2}, /*updates=*/{2}, kNoSync,
468 {2, 3, 4});
469 ConvertAndCheck(1, 6, /*references=*/{0}, /*updates=*/{1}, kSync, {4});
470 ConvertAndCheck(2, 7, /*references=*/{0, 1, 2}, /*updates=*/{2}, kNoSync,
471 {4, 5, 6});
philipelbf2b6202018-08-27 14:33:18 +0200472}
473
474TEST_F(RtpPayloadParamsVp8ToGenericTest, FrameIdGaps) {
475 // 0101 pattern
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100476 ConvertAndCheck(0, 0, /*references=*/{}, /*updates=*/{0}, kNoSync, {}, 480,
477 360);
478 ConvertAndCheck(1, 1, /*references=*/{0}, /*updates=*/{1}, kNoSync, {0});
philipelbf2b6202018-08-27 14:33:18 +0200479
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100480 ConvertAndCheck(0, 5, /*references=*/{0}, /*updates=*/{0}, kNoSync, {0});
481 ConvertAndCheck(1, 10, /*references=*/{0, 1}, /*updates=*/{1}, kNoSync,
482 {1, 5});
philipelbf2b6202018-08-27 14:33:18 +0200483
Danil Chapovalovdc7fe402019-12-13 12:23:58 +0100484 ConvertAndCheck(0, 15, /*references=*/{0}, /*updates=*/{0}, kNoSync, {5});
485 ConvertAndCheck(1, 20, /*references=*/{0, 1}, /*updates=*/{1}, kNoSync,
486 {10, 15});
philipelbf2b6202018-08-27 14:33:18 +0200487}
488
philipel8aba8fe2019-06-13 15:13:16 +0200489class RtpPayloadParamsH264ToGenericTest : public ::testing::Test {
490 public:
491 enum LayerSync { kNoSync, kSync };
492
493 RtpPayloadParamsH264ToGenericTest()
494 : generic_descriptor_field_trial_("WebRTC-GenericDescriptor/Enabled/"),
495 state_(),
496 params_(123, &state_) {}
497
498 void ConvertAndCheck(int temporal_index,
499 int64_t shared_frame_id,
500 VideoFrameType frame_type,
501 LayerSync layer_sync,
502 const std::set<int64_t>& expected_deps,
503 uint16_t width = 0,
504 uint16_t height = 0) {
505 EncodedImage encoded_image;
506 encoded_image._frameType = frame_type;
507 encoded_image._encodedWidth = width;
508 encoded_image._encodedHeight = height;
509
510 CodecSpecificInfo codec_info;
511 codec_info.codecType = kVideoCodecH264;
512 codec_info.codecSpecific.H264.temporal_idx = temporal_index;
513 codec_info.codecSpecific.H264.base_layer_sync = layer_sync == kSync;
514
515 RTPVideoHeader header =
516 params_.GetRtpVideoHeader(encoded_image, &codec_info, shared_frame_id);
517
518 ASSERT_TRUE(header.generic);
519 EXPECT_TRUE(header.generic->higher_spatial_layers.empty());
520 EXPECT_EQ(header.generic->spatial_index, 0);
521
522 EXPECT_EQ(header.generic->frame_id, shared_frame_id);
523 EXPECT_EQ(header.generic->temporal_index, temporal_index);
524 std::set<int64_t> actual_deps(header.generic->dependencies.begin(),
525 header.generic->dependencies.end());
526 EXPECT_EQ(expected_deps, actual_deps);
527
528 EXPECT_EQ(header.width, width);
529 EXPECT_EQ(header.height, height);
530 }
531
532 protected:
533 test::ScopedFieldTrials generic_descriptor_field_trial_;
534 RtpPayloadState state_;
535 RtpPayloadParams params_;
536};
537
538TEST_F(RtpPayloadParamsH264ToGenericTest, Keyframe) {
539 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
540 ConvertAndCheck(0, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
541 ConvertAndCheck(0, 2, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
542}
543
544TEST_F(RtpPayloadParamsH264ToGenericTest, TooHighTemporalIndex) {
545 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
546
547 EncodedImage encoded_image;
548 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
549 CodecSpecificInfo codec_info;
550 codec_info.codecType = kVideoCodecH264;
551 codec_info.codecSpecific.H264.temporal_idx =
552 RtpGenericFrameDescriptor::kMaxTemporalLayers;
553 codec_info.codecSpecific.H264.base_layer_sync = false;
554
555 RTPVideoHeader header =
556 params_.GetRtpVideoHeader(encoded_image, &codec_info, 1);
557 EXPECT_FALSE(header.generic);
558}
559
560TEST_F(RtpPayloadParamsH264ToGenericTest, LayerSync) {
561 // 02120212 pattern
562 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
563 ConvertAndCheck(2, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
564 ConvertAndCheck(1, 2, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
565 ConvertAndCheck(2, 3, VideoFrameType::kVideoFrameDelta, kNoSync, {0, 1, 2});
566
567 ConvertAndCheck(0, 4, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
568 ConvertAndCheck(2, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {2, 3, 4});
569 ConvertAndCheck(1, 6, VideoFrameType::kVideoFrameDelta, kSync,
570 {4}); // layer sync
571 ConvertAndCheck(2, 7, VideoFrameType::kVideoFrameDelta, kNoSync, {4, 5, 6});
572}
573
574TEST_F(RtpPayloadParamsH264ToGenericTest, FrameIdGaps) {
575 // 0101 pattern
576 ConvertAndCheck(0, 0, VideoFrameType::kVideoFrameKey, kNoSync, {}, 480, 360);
577 ConvertAndCheck(1, 1, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
578
579 ConvertAndCheck(0, 5, VideoFrameType::kVideoFrameDelta, kNoSync, {0});
580 ConvertAndCheck(1, 10, VideoFrameType::kVideoFrameDelta, kNoSync, {1, 5});
581
582 ConvertAndCheck(0, 15, VideoFrameType::kVideoFrameDelta, kNoSync, {5});
583 ConvertAndCheck(1, 20, VideoFrameType::kVideoFrameDelta, kNoSync, {10, 15});
584}
585
Stefan Holmerf7044682018-07-17 10:16:41 +0200586} // namespace webrtc