blob: a512582670d78d5e9ea65e0a381b48b3b0352d15 [file] [log] [blame]
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +00001/*
2 * Copyright (c) 2015 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
kwiberg27f982b2016-03-01 11:52:33 -080011#include <memory>
Åsa Persson4bece9a2017-10-06 10:04:04 +020012#include <string>
kwiberg27f982b2016-03-01 11:52:33 -080013
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "call/video_config.h"
15#include "modules/rtp_rtcp/include/rtp_rtcp.h"
16#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
17#include "modules/video_coding/include/video_codec_interface.h"
Åsa Persson4bece9a2017-10-06 10:04:04 +020018#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "test/gmock.h"
20#include "test/gtest.h"
21#include "video/payload_router.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000022
23using ::testing::_;
24using ::testing::AnyNumber;
Åsa Persson4bece9a2017-10-06 10:04:04 +020025using ::testing::Invoke;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000026using ::testing::NiceMock;
27using ::testing::Return;
Åsa Persson4bece9a2017-10-06 10:04:04 +020028using ::testing::Unused;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000029
30namespace webrtc {
Åsa Persson4bece9a2017-10-06 10:04:04 +020031namespace {
32const int8_t kPayloadType = 96;
33const uint32_t kSsrc1 = 12345;
34const uint32_t kSsrc2 = 23456;
Seth Hampson46e31ba2018-01-18 10:39:54 -080035const uint32_t kSsrc3 = 34567;
Åsa Persson4bece9a2017-10-06 10:04:04 +020036const int16_t kPictureId = 123;
37const int16_t kTl0PicIdx = 20;
38const uint8_t kTemporalIdx = 1;
39const int16_t kInitialPictureId1 = 222;
40const int16_t kInitialPictureId2 = 44;
41} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000042
Per83d09102016-04-15 14:59:13 +020043TEST(PayloadRouterTest, SendOnOneModule) {
perkjbc75d972016-05-02 06:31:25 -070044 NiceMock<MockRtpRtcp> rtp;
Peter Boström404686a2016-02-11 23:37:26 +010045 std::vector<RtpRtcp*> modules(1, &rtp);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000046
kjellander02b3d272016-04-20 05:05:54 -070047 uint8_t payload = 'a';
kjellander02b3d272016-04-20 05:05:54 -070048 EncodedImage encoded_image;
49 encoded_image._timeStamp = 1;
50 encoded_image.capture_time_ms_ = 2;
51 encoded_image._frameType = kVideoFrameKey;
52 encoded_image._buffer = &payload;
53 encoded_image._length = 1;
54
Åsa Persson4bece9a2017-10-06 10:04:04 +020055 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000056
Åsa Persson4bece9a2017-10-06 10:04:04 +020057 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070058 encoded_image._timeStamp,
59 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070060 encoded_image._length, nullptr, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000061 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -070062 EXPECT_NE(
63 EncodedImageCallback::Result::OK,
64 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000065
sprang1a646ee2016-12-01 06:34:11 -080066 payload_router.SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +020067 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070068 encoded_image._timeStamp,
69 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070070 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -080071 .Times(1)
72 .WillOnce(Return(true));
sergeyu2cb155a2016-11-04 11:39:29 -070073 EXPECT_EQ(
74 EncodedImageCallback::Result::OK,
75 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000076
sprang1a646ee2016-12-01 06:34:11 -080077 payload_router.SetActive(false);
Åsa Persson4bece9a2017-10-06 10:04:04 +020078 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070079 encoded_image._timeStamp,
80 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070081 encoded_image._length, nullptr, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000082 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -070083 EXPECT_NE(
84 EncodedImageCallback::Result::OK,
85 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000086
sprang1a646ee2016-12-01 06:34:11 -080087 payload_router.SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +020088 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070089 encoded_image._timeStamp,
90 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070091 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -080092 .Times(1)
93 .WillOnce(Return(true));
sergeyu2cb155a2016-11-04 11:39:29 -070094 EXPECT_EQ(
95 EncodedImageCallback::Result::OK,
96 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000097}
98
Per83d09102016-04-15 14:59:13 +020099TEST(PayloadRouterTest, SendSimulcast) {
perkjbc75d972016-05-02 06:31:25 -0700100 NiceMock<MockRtpRtcp> rtp_1;
101 NiceMock<MockRtpRtcp> rtp_2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200102 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2};
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000103
kjellander02b3d272016-04-20 05:05:54 -0700104 uint8_t payload = 'a';
105 EncodedImage encoded_image;
106 encoded_image._timeStamp = 1;
107 encoded_image.capture_time_ms_ = 2;
108 encoded_image._frameType = kVideoFrameKey;
109 encoded_image._buffer = &payload;
110 encoded_image._length = 1;
111
Åsa Persson4bece9a2017-10-06 10:04:04 +0200112 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000113
kjellander02b3d272016-04-20 05:05:54 -0700114 CodecSpecificInfo codec_info_1;
115 memset(&codec_info_1, 0, sizeof(CodecSpecificInfo));
116 codec_info_1.codecType = kVideoCodecVP8;
117 codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000118
sprang1a646ee2016-12-01 06:34:11 -0800119 payload_router.SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200120 EXPECT_CALL(rtp_1, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -0700121 encoded_image._timeStamp,
122 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700123 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -0800124 .Times(1)
125 .WillOnce(Return(true));
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700126 EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _, _)).Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700127 EXPECT_EQ(EncodedImageCallback::Result::OK,
128 payload_router.OnEncodedImage(encoded_image, &codec_info_1, nullptr)
129 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000130
kjellander02b3d272016-04-20 05:05:54 -0700131 CodecSpecificInfo codec_info_2;
132 memset(&codec_info_2, 0, sizeof(CodecSpecificInfo));
133 codec_info_2.codecType = kVideoCodecVP8;
134 codec_info_2.codecSpecific.VP8.simulcastIdx = 1;
135
Åsa Persson4bece9a2017-10-06 10:04:04 +0200136 EXPECT_CALL(rtp_2, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -0700137 encoded_image._timeStamp,
138 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700139 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -0800140 .Times(1)
141 .WillOnce(Return(true));
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700142 EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000143 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700144 EXPECT_EQ(EncodedImageCallback::Result::OK,
145 payload_router.OnEncodedImage(encoded_image, &codec_info_2, nullptr)
146 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000147
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000148 // Inactive.
sprang1a646ee2016-12-01 06:34:11 -0800149 payload_router.SetActive(false);
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700150 EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000151 .Times(0);
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700152 EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000153 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700154 EXPECT_NE(EncodedImageCallback::Result::OK,
155 payload_router.OnEncodedImage(encoded_image, &codec_info_1, nullptr)
156 .error);
157 EXPECT_NE(EncodedImageCallback::Result::OK,
158 payload_router.OnEncodedImage(encoded_image, &codec_info_2, nullptr)
159 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000160}
161
sprang1a646ee2016-12-01 06:34:11 -0800162TEST(PayloadRouterTest, SimulcastTargetBitrate) {
163 NiceMock<MockRtpRtcp> rtp_1;
164 NiceMock<MockRtpRtcp> rtp_2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200165 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2};
166
167 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
sprang1a646ee2016-12-01 06:34:11 -0800168 payload_router.SetActive(true);
169
170 BitrateAllocation bitrate;
171 bitrate.SetBitrate(0, 0, 10000);
172 bitrate.SetBitrate(0, 1, 20000);
173 bitrate.SetBitrate(1, 0, 40000);
174 bitrate.SetBitrate(1, 1, 80000);
175
176 BitrateAllocation layer0_bitrate;
177 layer0_bitrate.SetBitrate(0, 0, 10000);
178 layer0_bitrate.SetBitrate(0, 1, 20000);
179
180 BitrateAllocation layer1_bitrate;
181 layer1_bitrate.SetBitrate(0, 0, 40000);
182 layer1_bitrate.SetBitrate(0, 1, 80000);
183
184 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(layer0_bitrate)).Times(1);
185 EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(layer1_bitrate)).Times(1);
186
187 payload_router.OnBitrateAllocationUpdated(bitrate);
188}
189
Seth Hampson46e31ba2018-01-18 10:39:54 -0800190// If the middle of three streams is inactive the first and last streams should
191// be asked to send the TargetBitrate message.
sprangd0fc37a2017-06-22 05:40:25 -0700192TEST(PayloadRouterTest, SimulcastTargetBitrateWithInactiveStream) {
Seth Hampson46e31ba2018-01-18 10:39:54 -0800193 // Set up three active rtp modules.
sprangd0fc37a2017-06-22 05:40:25 -0700194 NiceMock<MockRtpRtcp> rtp_1;
195 NiceMock<MockRtpRtcp> rtp_2;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800196 NiceMock<MockRtpRtcp> rtp_3;
197 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2, &rtp_3};
198 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2, kSsrc3}, kPayloadType,
199 {});
sprangd0fc37a2017-06-22 05:40:25 -0700200 payload_router.SetActive(true);
201
Seth Hampson46e31ba2018-01-18 10:39:54 -0800202 // Create bitrate allocation with bitrate only for the first and third stream.
sprangd0fc37a2017-06-22 05:40:25 -0700203 BitrateAllocation bitrate;
204 bitrate.SetBitrate(0, 0, 10000);
205 bitrate.SetBitrate(0, 1, 20000);
Seth Hampson46e31ba2018-01-18 10:39:54 -0800206 bitrate.SetBitrate(2, 0, 40000);
207 bitrate.SetBitrate(2, 1, 80000);
sprangd0fc37a2017-06-22 05:40:25 -0700208
Seth Hampson46e31ba2018-01-18 10:39:54 -0800209 BitrateAllocation layer0_bitrate;
210 layer0_bitrate.SetBitrate(0, 0, 10000);
211 layer0_bitrate.SetBitrate(0, 1, 20000);
212
213 BitrateAllocation layer2_bitrate;
214 layer2_bitrate.SetBitrate(0, 0, 40000);
215 layer2_bitrate.SetBitrate(0, 1, 80000);
216
217 // Expect the first and third rtp module to be asked to send a TargetBitrate
sprangd0fc37a2017-06-22 05:40:25 -0700218 // message. (No target bitrate with 0bps sent from the second one.)
Seth Hampson46e31ba2018-01-18 10:39:54 -0800219 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(layer0_bitrate)).Times(1);
sprangd0fc37a2017-06-22 05:40:25 -0700220 EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(_)).Times(0);
Seth Hampson46e31ba2018-01-18 10:39:54 -0800221 EXPECT_CALL(rtp_3, SetVideoBitrateAllocation(layer2_bitrate)).Times(1);
sprangd0fc37a2017-06-22 05:40:25 -0700222
223 payload_router.OnBitrateAllocationUpdated(bitrate);
224}
225
sprang1a646ee2016-12-01 06:34:11 -0800226TEST(PayloadRouterTest, SvcTargetBitrate) {
227 NiceMock<MockRtpRtcp> rtp_1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200228 std::vector<RtpRtcp*> modules = {&rtp_1};
229 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
sprang1a646ee2016-12-01 06:34:11 -0800230 payload_router.SetActive(true);
231
232 BitrateAllocation bitrate;
233 bitrate.SetBitrate(0, 0, 10000);
234 bitrate.SetBitrate(0, 1, 20000);
235 bitrate.SetBitrate(1, 0, 40000);
236 bitrate.SetBitrate(1, 1, 80000);
237
238 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(bitrate)).Times(1);
239
240 payload_router.OnBitrateAllocationUpdated(bitrate);
241}
242
Åsa Persson4bece9a2017-10-06 10:04:04 +0200243TEST(PayloadRouterTest, InfoMappedToRtpVideoHeader_Vp8) {
244 NiceMock<MockRtpRtcp> rtp1;
245 NiceMock<MockRtpRtcp> rtp2;
246 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
247 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
248 payload_router.SetActive(true);
249
250 EncodedImage encoded_image;
251 encoded_image.rotation_ = kVideoRotation_90;
252 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
253
254 CodecSpecificInfo codec_info;
255 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
256 codec_info.codecType = kVideoCodecVP8;
257 codec_info.codecSpecific.VP8.simulcastIdx = 1;
258 codec_info.codecSpecific.VP8.pictureId = kPictureId;
259 codec_info.codecSpecific.VP8.temporalIdx = kTemporalIdx;
260 codec_info.codecSpecific.VP8.tl0PicIdx = kTl0PicIdx;
261 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
262 codec_info.codecSpecific.VP8.layerSync = true;
263 codec_info.codecSpecific.VP8.nonReference = true;
264
265 EXPECT_CALL(rtp2, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
266 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
267 Unused, const RTPVideoHeader* header, Unused) {
268 EXPECT_EQ(kVideoRotation_90, header->rotation);
269 EXPECT_EQ(VideoContentType::SCREENSHARE, header->content_type);
270 EXPECT_EQ(1, header->simulcastIdx);
271 EXPECT_EQ(kRtpVideoVp8, header->codec);
272 EXPECT_EQ(kPictureId, header->codecHeader.VP8.pictureId);
273 EXPECT_EQ(kTemporalIdx, header->codecHeader.VP8.temporalIdx);
274 EXPECT_EQ(kTl0PicIdx, header->codecHeader.VP8.tl0PicIdx);
275 EXPECT_EQ(kNoKeyIdx, header->codecHeader.VP8.keyIdx);
276 EXPECT_TRUE(header->codecHeader.VP8.layerSync);
277 EXPECT_TRUE(header->codecHeader.VP8.nonReference);
278 return true;
279 }));
280
281 EXPECT_EQ(
282 EncodedImageCallback::Result::OK,
283 payload_router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
284}
285
286TEST(PayloadRouterTest, InfoMappedToRtpVideoHeader_H264) {
287 NiceMock<MockRtpRtcp> rtp1;
288 std::vector<RtpRtcp*> modules = {&rtp1};
289 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
290 payload_router.SetActive(true);
291
292 EncodedImage encoded_image;
293 CodecSpecificInfo codec_info;
294 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
295 codec_info.codecType = kVideoCodecH264;
296 codec_info.codecSpecific.H264.packetization_mode =
297 H264PacketizationMode::SingleNalUnit;
298
299 EXPECT_CALL(rtp1, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
300 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
301 Unused, const RTPVideoHeader* header, Unused) {
302 EXPECT_EQ(0, header->simulcastIdx);
303 EXPECT_EQ(kRtpVideoH264, header->codec);
304 EXPECT_EQ(H264PacketizationMode::SingleNalUnit,
305 header->codecHeader.H264.packetization_mode);
306 return true;
307 }));
308
309 EXPECT_EQ(
310 EncodedImageCallback::Result::OK,
311 payload_router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
312}
313
314TEST(PayloadRouterTest, CreateWithNoPreviousStates) {
315 NiceMock<MockRtpRtcp> rtp1;
316 NiceMock<MockRtpRtcp> rtp2;
317 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
318 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
319 payload_router.SetActive(true);
320
321 std::map<uint32_t, RtpPayloadState> initial_states =
322 payload_router.GetRtpPayloadStates();
323 EXPECT_EQ(2u, initial_states.size());
324 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
325 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
326}
327
328TEST(PayloadRouterTest, CreateWithPreviousStates) {
329 RtpPayloadState state1;
330 state1.picture_id = kInitialPictureId1;
331 RtpPayloadState state2;
332 state2.picture_id = kInitialPictureId2;
333 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
334 {kSsrc2, state2}};
335
336 NiceMock<MockRtpRtcp> rtp1;
337 NiceMock<MockRtpRtcp> rtp2;
338 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
339 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, states);
340 payload_router.SetActive(true);
341
342 std::map<uint32_t, RtpPayloadState> initial_states =
343 payload_router.GetRtpPayloadStates();
344 EXPECT_EQ(2u, initial_states.size());
345 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
346 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
347}
348
349class PayloadRouterTest : public ::testing::Test {
350 public:
351 explicit PayloadRouterTest(const std::string& field_trials)
352 : override_field_trials_(field_trials) {}
353 virtual ~PayloadRouterTest() {}
354
355 protected:
356 virtual void SetUp() { memset(&codec_info_, 0, sizeof(CodecSpecificInfo)); }
357
358 test::ScopedFieldTrials override_field_trials_;
359 EncodedImage image_;
360 CodecSpecificInfo codec_info_;
361};
362
363class TestWithForcedFallbackDisabled : public PayloadRouterTest {
364 public:
365 TestWithForcedFallbackDisabled()
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100366 : PayloadRouterTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled/") {}
Åsa Persson4bece9a2017-10-06 10:04:04 +0200367};
368
369class TestWithForcedFallbackEnabled : public PayloadRouterTest {
370 public:
371 TestWithForcedFallbackEnabled()
372 : PayloadRouterTest(
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100373 "WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1,2,3/") {}
Åsa Persson4bece9a2017-10-06 10:04:04 +0200374};
375
376TEST_F(TestWithForcedFallbackDisabled, PictureIdIsNotChangedForVp8) {
377 NiceMock<MockRtpRtcp> rtp;
378 std::vector<RtpRtcp*> modules = {&rtp};
379 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {});
380 router.SetActive(true);
381
382 codec_info_.codecType = kVideoCodecVP8;
383 codec_info_.codecSpecific.VP8.pictureId = kPictureId;
384
385 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
386 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
387 Unused, const RTPVideoHeader* header, Unused) {
388 EXPECT_EQ(kRtpVideoVp8, header->codec);
389 EXPECT_EQ(kPictureId, header->codecHeader.VP8.pictureId);
390 return true;
391 }));
392
393 EXPECT_EQ(EncodedImageCallback::Result::OK,
394 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
395}
396
397TEST_F(TestWithForcedFallbackEnabled, PictureIdIsSetForVp8) {
398 RtpPayloadState state1;
399 state1.picture_id = kInitialPictureId1;
400 RtpPayloadState state2;
401 state2.picture_id = kInitialPictureId2;
402 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
403 {kSsrc2, state2}};
404
405 NiceMock<MockRtpRtcp> rtp1;
406 NiceMock<MockRtpRtcp> rtp2;
407 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
408 PayloadRouter router(modules, {kSsrc1, kSsrc2}, kPayloadType, states);
409 router.SetActive(true);
410
411 // OnEncodedImage, simulcastIdx: 0.
412 codec_info_.codecType = kVideoCodecVP8;
413 codec_info_.codecSpecific.VP8.pictureId = kPictureId;
414 codec_info_.codecSpecific.VP8.simulcastIdx = 0;
415
416 EXPECT_CALL(rtp1, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
417 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
418 Unused, const RTPVideoHeader* header, Unused) {
419 EXPECT_EQ(kRtpVideoVp8, header->codec);
420 EXPECT_EQ(kInitialPictureId1, header->codecHeader.VP8.pictureId);
421 return true;
422 }));
423
424 EXPECT_EQ(EncodedImageCallback::Result::OK,
425 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
426
427 // OnEncodedImage, simulcastIdx: 1.
428 codec_info_.codecSpecific.VP8.pictureId = kPictureId;
429 codec_info_.codecSpecific.VP8.simulcastIdx = 1;
430
431 EXPECT_CALL(rtp2, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
432 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
433 Unused, const RTPVideoHeader* header, Unused) {
434 EXPECT_EQ(kRtpVideoVp8, header->codec);
435 EXPECT_EQ(kInitialPictureId2, header->codecHeader.VP8.pictureId);
436 return true;
437 }));
438
439 EXPECT_EQ(EncodedImageCallback::Result::OK,
440 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
441
442 // State should hold next picture id to use.
443 states = router.GetRtpPayloadStates();
444 EXPECT_EQ(2u, states.size());
445 EXPECT_EQ(kInitialPictureId1 + 1, states[kSsrc1].picture_id);
446 EXPECT_EQ(kInitialPictureId2 + 1, states[kSsrc2].picture_id);
447}
448
449TEST_F(TestWithForcedFallbackEnabled, PictureIdWraps) {
450 RtpPayloadState state1;
451 state1.picture_id = kMaxTwoBytePictureId;
452
453 NiceMock<MockRtpRtcp> rtp;
454 std::vector<RtpRtcp*> modules = {&rtp};
455 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {{kSsrc1, state1}});
456 router.SetActive(true);
457
458 codec_info_.codecType = kVideoCodecVP8;
459 codec_info_.codecSpecific.VP8.pictureId = kPictureId;
460
461 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
462 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
463 Unused, const RTPVideoHeader* header, Unused) {
464 EXPECT_EQ(kRtpVideoVp8, header->codec);
465 EXPECT_EQ(kMaxTwoBytePictureId, header->codecHeader.VP8.pictureId);
466 return true;
467 }));
468
469 EXPECT_EQ(EncodedImageCallback::Result::OK,
470 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
471
472 // State should hold next picture id to use.
473 std::map<uint32_t, RtpPayloadState> states = router.GetRtpPayloadStates();
474 EXPECT_EQ(1u, states.size());
475 EXPECT_EQ(0, states[kSsrc1].picture_id); // Wrapped.
476}
477
478TEST_F(TestWithForcedFallbackEnabled, PictureIdIsNotSetIfNoPictureId) {
479 NiceMock<MockRtpRtcp> rtp;
480 std::vector<RtpRtcp*> modules = {&rtp};
481 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {});
482 router.SetActive(true);
483
484 codec_info_.codecType = kVideoCodecVP8;
485 codec_info_.codecSpecific.VP8.pictureId = kNoPictureId;
486
487 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
488 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
489 Unused, const RTPVideoHeader* header, Unused) {
490 EXPECT_EQ(kRtpVideoVp8, header->codec);
491 EXPECT_EQ(kNoPictureId, header->codecHeader.VP8.pictureId);
492 return true;
493 }));
494
495 EXPECT_EQ(EncodedImageCallback::Result::OK,
496 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
497}
498
499TEST_F(TestWithForcedFallbackEnabled, PictureIdIsNotSetForVp9) {
500 NiceMock<MockRtpRtcp> rtp;
501 std::vector<RtpRtcp*> modules = {&rtp};
502 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {});
503 router.SetActive(true);
504
505 codec_info_.codecType = kVideoCodecVP9;
506 codec_info_.codecSpecific.VP9.picture_id = kPictureId;
507
508 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
509 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
510 Unused, const RTPVideoHeader* header, Unused) {
511 EXPECT_EQ(kRtpVideoVp9, header->codec);
512 EXPECT_EQ(kPictureId, header->codecHeader.VP9.picture_id);
513 return true;
514 }));
515
516 EXPECT_EQ(EncodedImageCallback::Result::OK,
517 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
518}
519
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000520} // namespace webrtc