blob: 9e09dabd7ed6d655544d145dd8a2707027b9b917 [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;
Niels Möllerbb894ff2018-03-15 12:28:53 +010041const int16_t kInitialTl0PicIdx1 = 99;
42const int16_t kInitialTl0PicIdx2 = 199;
Åsa Persson4bece9a2017-10-06 10:04:04 +020043} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000044
Per83d09102016-04-15 14:59:13 +020045TEST(PayloadRouterTest, SendOnOneModule) {
perkjbc75d972016-05-02 06:31:25 -070046 NiceMock<MockRtpRtcp> rtp;
Peter Boström404686a2016-02-11 23:37:26 +010047 std::vector<RtpRtcp*> modules(1, &rtp);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000048
kjellander02b3d272016-04-20 05:05:54 -070049 uint8_t payload = 'a';
kjellander02b3d272016-04-20 05:05:54 -070050 EncodedImage encoded_image;
51 encoded_image._timeStamp = 1;
52 encoded_image.capture_time_ms_ = 2;
53 encoded_image._frameType = kVideoFrameKey;
54 encoded_image._buffer = &payload;
55 encoded_image._length = 1;
56
Åsa Persson4bece9a2017-10-06 10:04:04 +020057 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000058
Åsa Persson4bece9a2017-10-06 10:04:04 +020059 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070060 encoded_image._timeStamp,
61 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070062 encoded_image._length, nullptr, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000063 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -070064 EXPECT_NE(
65 EncodedImageCallback::Result::OK,
66 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000067
sprang1a646ee2016-12-01 06:34:11 -080068 payload_router.SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +020069 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070070 encoded_image._timeStamp,
71 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070072 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -080073 .Times(1)
74 .WillOnce(Return(true));
Seth Hampsoncc7125f2018-02-02 08:46:16 -080075 EXPECT_CALL(rtp, Sending()).WillOnce(Return(true));
sergeyu2cb155a2016-11-04 11:39:29 -070076 EXPECT_EQ(
77 EncodedImageCallback::Result::OK,
78 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000079
sprang1a646ee2016-12-01 06:34:11 -080080 payload_router.SetActive(false);
Åsa Persson4bece9a2017-10-06 10:04:04 +020081 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070082 encoded_image._timeStamp,
83 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070084 encoded_image._length, nullptr, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000085 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -070086 EXPECT_NE(
87 EncodedImageCallback::Result::OK,
88 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000089
sprang1a646ee2016-12-01 06:34:11 -080090 payload_router.SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +020091 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070092 encoded_image._timeStamp,
93 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070094 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -080095 .Times(1)
96 .WillOnce(Return(true));
Seth Hampsoncc7125f2018-02-02 08:46:16 -080097 EXPECT_CALL(rtp, Sending()).WillOnce(Return(true));
sergeyu2cb155a2016-11-04 11:39:29 -070098 EXPECT_EQ(
99 EncodedImageCallback::Result::OK,
100 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000101}
102
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800103TEST(PayloadRouterTest, SendSimulcastSetActive) {
perkjbc75d972016-05-02 06:31:25 -0700104 NiceMock<MockRtpRtcp> rtp_1;
105 NiceMock<MockRtpRtcp> rtp_2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200106 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2};
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000107
kjellander02b3d272016-04-20 05:05:54 -0700108 uint8_t payload = 'a';
109 EncodedImage encoded_image;
110 encoded_image._timeStamp = 1;
111 encoded_image.capture_time_ms_ = 2;
112 encoded_image._frameType = kVideoFrameKey;
113 encoded_image._buffer = &payload;
114 encoded_image._length = 1;
115
Åsa Persson4bece9a2017-10-06 10:04:04 +0200116 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000117
kjellander02b3d272016-04-20 05:05:54 -0700118 CodecSpecificInfo codec_info_1;
119 memset(&codec_info_1, 0, sizeof(CodecSpecificInfo));
120 codec_info_1.codecType = kVideoCodecVP8;
121 codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000122
sprang1a646ee2016-12-01 06:34:11 -0800123 payload_router.SetActive(true);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800124 EXPECT_CALL(rtp_1, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200125 EXPECT_CALL(rtp_1, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -0700126 encoded_image._timeStamp,
127 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700128 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -0800129 .Times(1)
130 .WillOnce(Return(true));
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700131 EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _, _)).Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700132 EXPECT_EQ(EncodedImageCallback::Result::OK,
133 payload_router.OnEncodedImage(encoded_image, &codec_info_1, nullptr)
134 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000135
kjellander02b3d272016-04-20 05:05:54 -0700136 CodecSpecificInfo codec_info_2;
137 memset(&codec_info_2, 0, sizeof(CodecSpecificInfo));
138 codec_info_2.codecType = kVideoCodecVP8;
139 codec_info_2.codecSpecific.VP8.simulcastIdx = 1;
140
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800141 EXPECT_CALL(rtp_2, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200142 EXPECT_CALL(rtp_2, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -0700143 encoded_image._timeStamp,
144 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700145 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -0800146 .Times(1)
147 .WillOnce(Return(true));
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700148 EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000149 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700150 EXPECT_EQ(EncodedImageCallback::Result::OK,
151 payload_router.OnEncodedImage(encoded_image, &codec_info_2, nullptr)
152 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000153
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000154 // Inactive.
sprang1a646ee2016-12-01 06:34:11 -0800155 payload_router.SetActive(false);
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700156 EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000157 .Times(0);
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700158 EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000159 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700160 EXPECT_NE(EncodedImageCallback::Result::OK,
161 payload_router.OnEncodedImage(encoded_image, &codec_info_1, nullptr)
162 .error);
163 EXPECT_NE(EncodedImageCallback::Result::OK,
164 payload_router.OnEncodedImage(encoded_image, &codec_info_2, nullptr)
165 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000166}
167
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800168// Tests how setting individual rtp modules to active affects the overall
169// behavior of the payload router. First sets one module to active and checks
170// that outgoing data can be sent on this module, and checks that no data can be
171// sent if both modules are inactive.
172TEST(PayloadRouterTest, SendSimulcastSetActiveModules) {
173 NiceMock<MockRtpRtcp> rtp_1;
174 NiceMock<MockRtpRtcp> rtp_2;
175 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2};
176
177 uint8_t payload = 'a';
178 EncodedImage encoded_image;
179 encoded_image._timeStamp = 1;
180 encoded_image.capture_time_ms_ = 2;
181 encoded_image._frameType = kVideoFrameKey;
182 encoded_image._buffer = &payload;
183 encoded_image._length = 1;
184 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
185 CodecSpecificInfo codec_info_1;
186 memset(&codec_info_1, 0, sizeof(CodecSpecificInfo));
187 codec_info_1.codecType = kVideoCodecVP8;
188 codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
189 CodecSpecificInfo codec_info_2;
190 memset(&codec_info_2, 0, sizeof(CodecSpecificInfo));
191 codec_info_2.codecType = kVideoCodecVP8;
192 codec_info_2.codecSpecific.VP8.simulcastIdx = 1;
193
194 // Only setting one stream to active will still set the payload router to
195 // active and allow sending data on the active stream.
196 std::vector<bool> active_modules({true, false});
197 payload_router.SetActiveModules(active_modules);
198
199 EXPECT_CALL(rtp_1, Sending()).WillOnce(Return(true));
200 EXPECT_CALL(rtp_1, SendOutgoingData(encoded_image._frameType, kPayloadType,
201 encoded_image._timeStamp,
202 encoded_image.capture_time_ms_, &payload,
203 encoded_image._length, nullptr, _, _))
204 .Times(1)
205 .WillOnce(Return(true));
206 EXPECT_EQ(EncodedImageCallback::Result::OK,
207 payload_router.OnEncodedImage(encoded_image, &codec_info_1, nullptr)
208 .error);
209
210 // Setting both streams to inactive will turn the payload router to inactive.
211 active_modules = {false, false};
212 payload_router.SetActiveModules(active_modules);
213 // An incoming encoded image will not ask the module to send outgoing data
214 // because the payload router is inactive.
215 EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _, _)).Times(0);
216 EXPECT_CALL(rtp_1, Sending()).Times(0);
217 EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _, _)).Times(0);
218 EXPECT_CALL(rtp_2, Sending()).Times(0);
219 EXPECT_NE(EncodedImageCallback::Result::OK,
220 payload_router.OnEncodedImage(encoded_image, &codec_info_1, nullptr)
221 .error);
222 EXPECT_NE(EncodedImageCallback::Result::OK,
223 payload_router.OnEncodedImage(encoded_image, &codec_info_2, nullptr)
224 .error);
225}
226
sprang1a646ee2016-12-01 06:34:11 -0800227TEST(PayloadRouterTest, SimulcastTargetBitrate) {
228 NiceMock<MockRtpRtcp> rtp_1;
229 NiceMock<MockRtpRtcp> rtp_2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200230 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2};
231
232 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
sprang1a646ee2016-12-01 06:34:11 -0800233 payload_router.SetActive(true);
234
235 BitrateAllocation bitrate;
236 bitrate.SetBitrate(0, 0, 10000);
237 bitrate.SetBitrate(0, 1, 20000);
238 bitrate.SetBitrate(1, 0, 40000);
239 bitrate.SetBitrate(1, 1, 80000);
240
241 BitrateAllocation layer0_bitrate;
242 layer0_bitrate.SetBitrate(0, 0, 10000);
243 layer0_bitrate.SetBitrate(0, 1, 20000);
244
245 BitrateAllocation layer1_bitrate;
246 layer1_bitrate.SetBitrate(0, 0, 40000);
247 layer1_bitrate.SetBitrate(0, 1, 80000);
248
249 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(layer0_bitrate)).Times(1);
250 EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(layer1_bitrate)).Times(1);
251
252 payload_router.OnBitrateAllocationUpdated(bitrate);
253}
254
Seth Hampson46e31ba2018-01-18 10:39:54 -0800255// If the middle of three streams is inactive the first and last streams should
256// be asked to send the TargetBitrate message.
sprangd0fc37a2017-06-22 05:40:25 -0700257TEST(PayloadRouterTest, SimulcastTargetBitrateWithInactiveStream) {
Seth Hampson46e31ba2018-01-18 10:39:54 -0800258 // Set up three active rtp modules.
sprangd0fc37a2017-06-22 05:40:25 -0700259 NiceMock<MockRtpRtcp> rtp_1;
260 NiceMock<MockRtpRtcp> rtp_2;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800261 NiceMock<MockRtpRtcp> rtp_3;
262 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2, &rtp_3};
263 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2, kSsrc3}, kPayloadType,
264 {});
sprangd0fc37a2017-06-22 05:40:25 -0700265 payload_router.SetActive(true);
266
Seth Hampson46e31ba2018-01-18 10:39:54 -0800267 // Create bitrate allocation with bitrate only for the first and third stream.
sprangd0fc37a2017-06-22 05:40:25 -0700268 BitrateAllocation bitrate;
269 bitrate.SetBitrate(0, 0, 10000);
270 bitrate.SetBitrate(0, 1, 20000);
Seth Hampson46e31ba2018-01-18 10:39:54 -0800271 bitrate.SetBitrate(2, 0, 40000);
272 bitrate.SetBitrate(2, 1, 80000);
sprangd0fc37a2017-06-22 05:40:25 -0700273
Seth Hampson46e31ba2018-01-18 10:39:54 -0800274 BitrateAllocation layer0_bitrate;
275 layer0_bitrate.SetBitrate(0, 0, 10000);
276 layer0_bitrate.SetBitrate(0, 1, 20000);
277
278 BitrateAllocation layer2_bitrate;
279 layer2_bitrate.SetBitrate(0, 0, 40000);
280 layer2_bitrate.SetBitrate(0, 1, 80000);
281
282 // Expect the first and third rtp module to be asked to send a TargetBitrate
sprangd0fc37a2017-06-22 05:40:25 -0700283 // message. (No target bitrate with 0bps sent from the second one.)
Seth Hampson46e31ba2018-01-18 10:39:54 -0800284 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(layer0_bitrate)).Times(1);
sprangd0fc37a2017-06-22 05:40:25 -0700285 EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(_)).Times(0);
Seth Hampson46e31ba2018-01-18 10:39:54 -0800286 EXPECT_CALL(rtp_3, SetVideoBitrateAllocation(layer2_bitrate)).Times(1);
sprangd0fc37a2017-06-22 05:40:25 -0700287
288 payload_router.OnBitrateAllocationUpdated(bitrate);
289}
290
sprang1a646ee2016-12-01 06:34:11 -0800291TEST(PayloadRouterTest, SvcTargetBitrate) {
292 NiceMock<MockRtpRtcp> rtp_1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200293 std::vector<RtpRtcp*> modules = {&rtp_1};
294 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
sprang1a646ee2016-12-01 06:34:11 -0800295 payload_router.SetActive(true);
296
297 BitrateAllocation bitrate;
298 bitrate.SetBitrate(0, 0, 10000);
299 bitrate.SetBitrate(0, 1, 20000);
300 bitrate.SetBitrate(1, 0, 40000);
301 bitrate.SetBitrate(1, 1, 80000);
302
303 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(bitrate)).Times(1);
304
305 payload_router.OnBitrateAllocationUpdated(bitrate);
306}
307
Åsa Persson4bece9a2017-10-06 10:04:04 +0200308TEST(PayloadRouterTest, InfoMappedToRtpVideoHeader_Vp8) {
309 NiceMock<MockRtpRtcp> rtp1;
310 NiceMock<MockRtpRtcp> rtp2;
311 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
Niels Möllerbb894ff2018-03-15 12:28:53 +0100312 RtpPayloadState state2;
313 state2.picture_id = kPictureId;
314 state2.tl0_pic_idx = kTl0PicIdx;
315 std::map<uint32_t, RtpPayloadState> states = {{kSsrc2, state2}};
316
317 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, states);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200318 payload_router.SetActive(true);
319
320 EncodedImage encoded_image;
321 encoded_image.rotation_ = kVideoRotation_90;
322 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
323
324 CodecSpecificInfo codec_info;
325 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
326 codec_info.codecType = kVideoCodecVP8;
327 codec_info.codecSpecific.VP8.simulcastIdx = 1;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100328 codec_info.codecSpecific.VP8.pictureId = -1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200329 codec_info.codecSpecific.VP8.temporalIdx = kTemporalIdx;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200330 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
331 codec_info.codecSpecific.VP8.layerSync = true;
332 codec_info.codecSpecific.VP8.nonReference = true;
333
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800334 EXPECT_CALL(rtp2, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200335 EXPECT_CALL(rtp2, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
336 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
337 Unused, const RTPVideoHeader* header, Unused) {
338 EXPECT_EQ(kVideoRotation_90, header->rotation);
339 EXPECT_EQ(VideoContentType::SCREENSHARE, header->content_type);
340 EXPECT_EQ(1, header->simulcastIdx);
341 EXPECT_EQ(kRtpVideoVp8, header->codec);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100342 EXPECT_EQ(kPictureId + 1, header->codecHeader.VP8.pictureId);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200343 EXPECT_EQ(kTemporalIdx, header->codecHeader.VP8.temporalIdx);
344 EXPECT_EQ(kTl0PicIdx, header->codecHeader.VP8.tl0PicIdx);
345 EXPECT_EQ(kNoKeyIdx, header->codecHeader.VP8.keyIdx);
346 EXPECT_TRUE(header->codecHeader.VP8.layerSync);
347 EXPECT_TRUE(header->codecHeader.VP8.nonReference);
348 return true;
349 }));
350
351 EXPECT_EQ(
352 EncodedImageCallback::Result::OK,
353 payload_router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
354}
355
356TEST(PayloadRouterTest, InfoMappedToRtpVideoHeader_H264) {
357 NiceMock<MockRtpRtcp> rtp1;
358 std::vector<RtpRtcp*> modules = {&rtp1};
359 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
360 payload_router.SetActive(true);
361
362 EncodedImage encoded_image;
363 CodecSpecificInfo codec_info;
364 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
365 codec_info.codecType = kVideoCodecH264;
366 codec_info.codecSpecific.H264.packetization_mode =
367 H264PacketizationMode::SingleNalUnit;
368
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800369 EXPECT_CALL(rtp1, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200370 EXPECT_CALL(rtp1, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
371 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
372 Unused, const RTPVideoHeader* header, Unused) {
373 EXPECT_EQ(0, header->simulcastIdx);
374 EXPECT_EQ(kRtpVideoH264, header->codec);
375 EXPECT_EQ(H264PacketizationMode::SingleNalUnit,
376 header->codecHeader.H264.packetization_mode);
377 return true;
378 }));
379
380 EXPECT_EQ(
381 EncodedImageCallback::Result::OK,
382 payload_router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
383}
384
385TEST(PayloadRouterTest, CreateWithNoPreviousStates) {
386 NiceMock<MockRtpRtcp> rtp1;
387 NiceMock<MockRtpRtcp> rtp2;
388 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
389 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
390 payload_router.SetActive(true);
391
392 std::map<uint32_t, RtpPayloadState> initial_states =
393 payload_router.GetRtpPayloadStates();
394 EXPECT_EQ(2u, initial_states.size());
395 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
396 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
397}
398
399TEST(PayloadRouterTest, CreateWithPreviousStates) {
400 RtpPayloadState state1;
401 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100402 state1.tl0_pic_idx = kInitialTl0PicIdx1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200403 RtpPayloadState state2;
404 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100405 state2.tl0_pic_idx = kInitialTl0PicIdx2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200406 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
407 {kSsrc2, state2}};
408
409 NiceMock<MockRtpRtcp> rtp1;
410 NiceMock<MockRtpRtcp> rtp2;
411 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
412 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, states);
413 payload_router.SetActive(true);
414
415 std::map<uint32_t, RtpPayloadState> initial_states =
416 payload_router.GetRtpPayloadStates();
417 EXPECT_EQ(2u, initial_states.size());
418 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100419 EXPECT_EQ(kInitialTl0PicIdx1, initial_states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200420 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100421 EXPECT_EQ(kInitialTl0PicIdx2, initial_states[kSsrc2].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200422}
423
Niels Möllerbb894ff2018-03-15 12:28:53 +0100424TEST(PayloadRouterTest, PictureIdIsSetForVp8) {
Åsa Persson4bece9a2017-10-06 10:04:04 +0200425 RtpPayloadState state1;
426 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100427 state1.tl0_pic_idx = kInitialTl0PicIdx1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200428 RtpPayloadState state2;
429 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100430 state2.tl0_pic_idx = kInitialTl0PicIdx2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200431 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
432 {kSsrc2, state2}};
433
434 NiceMock<MockRtpRtcp> rtp1;
435 NiceMock<MockRtpRtcp> rtp2;
436 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
437 PayloadRouter router(modules, {kSsrc1, kSsrc2}, kPayloadType, states);
438 router.SetActive(true);
439
Niels Möllerbb894ff2018-03-15 12:28:53 +0100440 EncodedImage encoded_image;
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800441 // Modules are sending for this test.
Åsa Persson4bece9a2017-10-06 10:04:04 +0200442 // OnEncodedImage, simulcastIdx: 0.
Niels Möllerbb894ff2018-03-15 12:28:53 +0100443 CodecSpecificInfo codec_info;
444 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
445 codec_info.codecType = kVideoCodecVP8;
446 codec_info.codecSpecific.VP8.simulcastIdx = 0;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200447
448 EXPECT_CALL(rtp1, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
449 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
450 Unused, const RTPVideoHeader* header, Unused) {
451 EXPECT_EQ(kRtpVideoVp8, header->codec);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100452 EXPECT_EQ(kInitialPictureId1 + 1, header->codecHeader.VP8.pictureId);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200453 return true;
454 }));
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800455 EXPECT_CALL(rtp1, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200456
457 EXPECT_EQ(EncodedImageCallback::Result::OK,
Niels Möllerbb894ff2018-03-15 12:28:53 +0100458 router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200459
460 // OnEncodedImage, simulcastIdx: 1.
Niels Möllerbb894ff2018-03-15 12:28:53 +0100461 codec_info.codecSpecific.VP8.simulcastIdx = 1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200462
463 EXPECT_CALL(rtp2, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
464 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
465 Unused, const RTPVideoHeader* header, Unused) {
466 EXPECT_EQ(kRtpVideoVp8, header->codec);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100467 EXPECT_EQ(kInitialPictureId2 + 1, header->codecHeader.VP8.pictureId);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200468 return true;
469 }));
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800470 EXPECT_CALL(rtp2, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200471
472 EXPECT_EQ(EncodedImageCallback::Result::OK,
Niels Möllerbb894ff2018-03-15 12:28:53 +0100473 router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200474
Niels Möllerbb894ff2018-03-15 12:28:53 +0100475 // State should hold latest used picture id and tl0_pic_idx.
Åsa Persson4bece9a2017-10-06 10:04:04 +0200476 states = router.GetRtpPayloadStates();
477 EXPECT_EQ(2u, states.size());
478 EXPECT_EQ(kInitialPictureId1 + 1, states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100479 EXPECT_EQ(kInitialTl0PicIdx1 + 1, states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200480 EXPECT_EQ(kInitialPictureId2 + 1, states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100481 EXPECT_EQ(kInitialTl0PicIdx2 + 1, states[kSsrc2].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200482}
483
Niels Möllerbb894ff2018-03-15 12:28:53 +0100484TEST(PayloadRouterTest, PictureIdWraps) {
Åsa Persson4bece9a2017-10-06 10:04:04 +0200485 RtpPayloadState state1;
486 state1.picture_id = kMaxTwoBytePictureId;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100487 state1.tl0_pic_idx = kInitialTl0PicIdx1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200488
489 NiceMock<MockRtpRtcp> rtp;
490 std::vector<RtpRtcp*> modules = {&rtp};
491 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {{kSsrc1, state1}});
492 router.SetActive(true);
493
Niels Möllerbb894ff2018-03-15 12:28:53 +0100494 EncodedImage encoded_image;
495 CodecSpecificInfo codec_info;
496 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
497 codec_info.codecType = kVideoCodecVP8;
498 codec_info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200499
500 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
501 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
502 Unused, const RTPVideoHeader* header, Unused) {
503 EXPECT_EQ(kRtpVideoVp8, header->codec);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100504 EXPECT_EQ(0, header->codecHeader.VP8.pictureId);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200505 return true;
506 }));
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800507 EXPECT_CALL(rtp, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200508
509 EXPECT_EQ(EncodedImageCallback::Result::OK,
Niels Möllerbb894ff2018-03-15 12:28:53 +0100510 router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200511
Niels Möllerbb894ff2018-03-15 12:28:53 +0100512 // State should hold latest used picture id and tl0_pic_idx.
Åsa Persson4bece9a2017-10-06 10:04:04 +0200513 std::map<uint32_t, RtpPayloadState> states = router.GetRtpPayloadStates();
514 EXPECT_EQ(1u, states.size());
515 EXPECT_EQ(0, states[kSsrc1].picture_id); // Wrapped.
Niels Möllerbb894ff2018-03-15 12:28:53 +0100516 EXPECT_EQ(kInitialTl0PicIdx1, states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200517}
518
Niels Möllerbb894ff2018-03-15 12:28:53 +0100519TEST(PayloadRouterTest, Tl0PicIdxUpdatedForVp8) {
520 RtpPayloadState state;
521 state.picture_id = kInitialPictureId1;
522 state.tl0_pic_idx = kInitialTl0PicIdx1;
523 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state}};
524
Åsa Persson4bece9a2017-10-06 10:04:04 +0200525 NiceMock<MockRtpRtcp> rtp;
526 std::vector<RtpRtcp*> modules = {&rtp};
Niels Möllerbb894ff2018-03-15 12:28:53 +0100527 PayloadRouter router(modules, {kSsrc1}, kPayloadType, states);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200528 router.SetActive(true);
529
Niels Möllerbb894ff2018-03-15 12:28:53 +0100530 EncodedImage encoded_image;
531 // Modules are sending for this test.
532 // OnEncodedImage, temporalIdx: 1.
533 CodecSpecificInfo codec_info;
534 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
535 codec_info.codecType = kVideoCodecVP8;
536 codec_info.codecSpecific.VP8.temporalIdx = 1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200537
538 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
539 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
540 Unused, const RTPVideoHeader* header, Unused) {
541 EXPECT_EQ(kRtpVideoVp8, header->codec);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100542 EXPECT_EQ(kInitialPictureId1 + 1, header->codecHeader.VP8.pictureId);
543 EXPECT_EQ(kInitialTl0PicIdx1, header->codecHeader.VP8.tl0PicIdx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200544 return true;
545 }));
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800546 EXPECT_CALL(rtp, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200547
548 EXPECT_EQ(EncodedImageCallback::Result::OK,
Niels Möllerbb894ff2018-03-15 12:28:53 +0100549 router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
550
551 // OnEncodedImage, temporalIdx: 0.
552 codec_info.codecSpecific.VP8.temporalIdx = 0;
553
554 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
555 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
556 Unused, const RTPVideoHeader* header, Unused) {
557 EXPECT_EQ(kRtpVideoVp8, header->codec);
558 EXPECT_EQ(kInitialPictureId1 + 2, header->codecHeader.VP8.pictureId);
559 EXPECT_EQ(kInitialTl0PicIdx1 + 1, header->codecHeader.VP8.tl0PicIdx);
560 return true;
561 }));
562 EXPECT_CALL(rtp, Sending()).WillOnce(Return(true));
563
564 EXPECT_EQ(EncodedImageCallback::Result::OK,
565 router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
566
567 // State should hold latest used picture id and tl0_pic_idx.
568 states = router.GetRtpPayloadStates();
569 EXPECT_EQ(1u, states.size());
570 EXPECT_EQ(kInitialPictureId1 + 2, states[kSsrc1].picture_id);
571 EXPECT_EQ(kInitialTl0PicIdx1 + 1, states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200572}
573
Niels Möllerbb894ff2018-03-15 12:28:53 +0100574TEST(PayloadRouterTest, Tl0PicIdxUpdatedForVp9) {
575 RtpPayloadState state;
576 state.picture_id = kInitialPictureId1;
577 state.tl0_pic_idx = kInitialTl0PicIdx1;
578 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state}};
579
Åsa Persson4bece9a2017-10-06 10:04:04 +0200580 NiceMock<MockRtpRtcp> rtp;
581 std::vector<RtpRtcp*> modules = {&rtp};
Niels Möllerbb894ff2018-03-15 12:28:53 +0100582 PayloadRouter router(modules, {kSsrc1}, kPayloadType, states);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200583 router.SetActive(true);
584
Niels Möllerbb894ff2018-03-15 12:28:53 +0100585 EncodedImage encoded_image;
586 // Modules are sending for this test.
587 // OnEncodedImage, temporalIdx: 1.
588 CodecSpecificInfo codec_info;
589 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
590 codec_info.codecType = kVideoCodecVP9;
591 codec_info.codecSpecific.VP9.temporal_idx = 1;
592 codec_info.codecSpecific.VP9.first_frame_in_picture = true;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200593
594 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
595 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
596 Unused, const RTPVideoHeader* header, Unused) {
597 EXPECT_EQ(kRtpVideoVp9, header->codec);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100598 EXPECT_EQ(kInitialPictureId1 + 1, header->codecHeader.VP9.picture_id);
599 EXPECT_EQ(kInitialTl0PicIdx1, header->codecHeader.VP9.tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200600 return true;
601 }));
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800602 EXPECT_CALL(rtp, Sending()).WillOnce(Return(true));
Åsa Persson4bece9a2017-10-06 10:04:04 +0200603
604 EXPECT_EQ(EncodedImageCallback::Result::OK,
Niels Möllerbb894ff2018-03-15 12:28:53 +0100605 router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
606
607 // OnEncodedImage, temporalIdx: 0.
608 codec_info.codecSpecific.VP9.temporal_idx = 0;
609
610 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
611 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
612 Unused, const RTPVideoHeader* header, Unused) {
613 EXPECT_EQ(kRtpVideoVp9, header->codec);
614 EXPECT_EQ(kInitialPictureId1 + 2, header->codecHeader.VP9.picture_id);
615 EXPECT_EQ(kInitialTl0PicIdx1 + 1, header->codecHeader.VP9.tl0_pic_idx);
616 return true;
617 }));
618 EXPECT_CALL(rtp, Sending()).WillOnce(Return(true));
619
620 EXPECT_EQ(EncodedImageCallback::Result::OK,
621 router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
622
623 // OnEncodedImage, first_frame_in_picture = false
624 codec_info.codecSpecific.VP9.first_frame_in_picture = false;
625
626 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
627 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
628 Unused, const RTPVideoHeader* header, Unused) {
629 EXPECT_EQ(kRtpVideoVp9, header->codec);
630 EXPECT_EQ(kInitialPictureId1 + 2, header->codecHeader.VP9.picture_id);
631 EXPECT_EQ(kInitialTl0PicIdx1 + 1, header->codecHeader.VP9.tl0_pic_idx);
632 return true;
633 }));
634 EXPECT_CALL(rtp, Sending()).WillOnce(Return(true));
635
636 EXPECT_EQ(EncodedImageCallback::Result::OK,
637 router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
638
639 // State should hold latest used picture id and tl0_pic_idx.
640 states = router.GetRtpPayloadStates();
641 EXPECT_EQ(1u, states.size());
642 EXPECT_EQ(kInitialPictureId1 + 2, states[kSsrc1].picture_id);
643 EXPECT_EQ(kInitialTl0PicIdx1 + 1, states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200644}
645
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000646} // namespace webrtc