blob: fe4ea12bdae06e320d6a0be3238cd5c35bc020cc [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;
35const int16_t kPictureId = 123;
36const int16_t kTl0PicIdx = 20;
37const uint8_t kTemporalIdx = 1;
38const int16_t kInitialPictureId1 = 222;
39const int16_t kInitialPictureId2 = 44;
40} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000041
Per83d09102016-04-15 14:59:13 +020042TEST(PayloadRouterTest, SendOnOneModule) {
perkjbc75d972016-05-02 06:31:25 -070043 NiceMock<MockRtpRtcp> rtp;
Peter Boström404686a2016-02-11 23:37:26 +010044 std::vector<RtpRtcp*> modules(1, &rtp);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000045
kjellander02b3d272016-04-20 05:05:54 -070046 uint8_t payload = 'a';
kjellander02b3d272016-04-20 05:05:54 -070047 EncodedImage encoded_image;
48 encoded_image._timeStamp = 1;
49 encoded_image.capture_time_ms_ = 2;
50 encoded_image._frameType = kVideoFrameKey;
51 encoded_image._buffer = &payload;
52 encoded_image._length = 1;
53
Åsa Persson4bece9a2017-10-06 10:04:04 +020054 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000055
Åsa Persson4bece9a2017-10-06 10:04:04 +020056 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070057 encoded_image._timeStamp,
58 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070059 encoded_image._length, nullptr, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000060 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -070061 EXPECT_NE(
62 EncodedImageCallback::Result::OK,
63 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000064
sprang1a646ee2016-12-01 06:34:11 -080065 payload_router.SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +020066 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070067 encoded_image._timeStamp,
68 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070069 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -080070 .Times(1)
71 .WillOnce(Return(true));
sergeyu2cb155a2016-11-04 11:39:29 -070072 EXPECT_EQ(
73 EncodedImageCallback::Result::OK,
74 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000075
sprang1a646ee2016-12-01 06:34:11 -080076 payload_router.SetActive(false);
Åsa Persson4bece9a2017-10-06 10:04:04 +020077 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070078 encoded_image._timeStamp,
79 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070080 encoded_image._length, nullptr, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000081 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -070082 EXPECT_NE(
83 EncodedImageCallback::Result::OK,
84 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000085
sprang1a646ee2016-12-01 06:34:11 -080086 payload_router.SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +020087 EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -070088 encoded_image._timeStamp,
89 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -070090 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -080091 .Times(1)
92 .WillOnce(Return(true));
sergeyu2cb155a2016-11-04 11:39:29 -070093 EXPECT_EQ(
94 EncodedImageCallback::Result::OK,
95 payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000096}
97
Per83d09102016-04-15 14:59:13 +020098TEST(PayloadRouterTest, SendSimulcast) {
perkjbc75d972016-05-02 06:31:25 -070099 NiceMock<MockRtpRtcp> rtp_1;
100 NiceMock<MockRtpRtcp> rtp_2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200101 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2};
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000102
kjellander02b3d272016-04-20 05:05:54 -0700103 uint8_t payload = 'a';
104 EncodedImage encoded_image;
105 encoded_image._timeStamp = 1;
106 encoded_image.capture_time_ms_ = 2;
107 encoded_image._frameType = kVideoFrameKey;
108 encoded_image._buffer = &payload;
109 encoded_image._length = 1;
110
Åsa Persson4bece9a2017-10-06 10:04:04 +0200111 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000112
kjellander02b3d272016-04-20 05:05:54 -0700113 CodecSpecificInfo codec_info_1;
114 memset(&codec_info_1, 0, sizeof(CodecSpecificInfo));
115 codec_info_1.codecType = kVideoCodecVP8;
116 codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000117
sprang1a646ee2016-12-01 06:34:11 -0800118 payload_router.SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200119 EXPECT_CALL(rtp_1, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -0700120 encoded_image._timeStamp,
121 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700122 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -0800123 .Times(1)
124 .WillOnce(Return(true));
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700125 EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _, _)).Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700126 EXPECT_EQ(EncodedImageCallback::Result::OK,
127 payload_router.OnEncodedImage(encoded_image, &codec_info_1, nullptr)
128 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000129
kjellander02b3d272016-04-20 05:05:54 -0700130 CodecSpecificInfo codec_info_2;
131 memset(&codec_info_2, 0, sizeof(CodecSpecificInfo));
132 codec_info_2.codecType = kVideoCodecVP8;
133 codec_info_2.codecSpecific.VP8.simulcastIdx = 1;
134
Åsa Persson4bece9a2017-10-06 10:04:04 +0200135 EXPECT_CALL(rtp_2, SendOutgoingData(encoded_image._frameType, kPayloadType,
kjellander02b3d272016-04-20 05:05:54 -0700136 encoded_image._timeStamp,
137 encoded_image.capture_time_ms_, &payload,
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700138 encoded_image._length, nullptr, _, _))
sergeyu7b9feee2016-11-17 16:16:14 -0800139 .Times(1)
140 .WillOnce(Return(true));
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700141 EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000142 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700143 EXPECT_EQ(EncodedImageCallback::Result::OK,
144 payload_router.OnEncodedImage(encoded_image, &codec_info_2, nullptr)
145 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000146
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000147 // Inactive.
sprang1a646ee2016-12-01 06:34:11 -0800148 payload_router.SetActive(false);
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700149 EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000150 .Times(0);
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700151 EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _, _))
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000152 .Times(0);
sergeyu2cb155a2016-11-04 11:39:29 -0700153 EXPECT_NE(EncodedImageCallback::Result::OK,
154 payload_router.OnEncodedImage(encoded_image, &codec_info_1, nullptr)
155 .error);
156 EXPECT_NE(EncodedImageCallback::Result::OK,
157 payload_router.OnEncodedImage(encoded_image, &codec_info_2, nullptr)
158 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000159}
160
sprang1a646ee2016-12-01 06:34:11 -0800161TEST(PayloadRouterTest, SimulcastTargetBitrate) {
162 NiceMock<MockRtpRtcp> rtp_1;
163 NiceMock<MockRtpRtcp> rtp_2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200164 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2};
165
166 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
sprang1a646ee2016-12-01 06:34:11 -0800167 payload_router.SetActive(true);
168
169 BitrateAllocation bitrate;
170 bitrate.SetBitrate(0, 0, 10000);
171 bitrate.SetBitrate(0, 1, 20000);
172 bitrate.SetBitrate(1, 0, 40000);
173 bitrate.SetBitrate(1, 1, 80000);
174
175 BitrateAllocation layer0_bitrate;
176 layer0_bitrate.SetBitrate(0, 0, 10000);
177 layer0_bitrate.SetBitrate(0, 1, 20000);
178
179 BitrateAllocation layer1_bitrate;
180 layer1_bitrate.SetBitrate(0, 0, 40000);
181 layer1_bitrate.SetBitrate(0, 1, 80000);
182
183 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(layer0_bitrate)).Times(1);
184 EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(layer1_bitrate)).Times(1);
185
186 payload_router.OnBitrateAllocationUpdated(bitrate);
187}
188
sprangd0fc37a2017-06-22 05:40:25 -0700189TEST(PayloadRouterTest, SimulcastTargetBitrateWithInactiveStream) {
190 // Set up two active rtp modules.
191 NiceMock<MockRtpRtcp> rtp_1;
192 NiceMock<MockRtpRtcp> rtp_2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200193 std::vector<RtpRtcp*> modules = {&rtp_1, &rtp_2};
194 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
sprangd0fc37a2017-06-22 05:40:25 -0700195 payload_router.SetActive(true);
196
197 // Create bitrate allocation with bitrate only for the first stream.
198 BitrateAllocation bitrate;
199 bitrate.SetBitrate(0, 0, 10000);
200 bitrate.SetBitrate(0, 1, 20000);
201
202 // Expect only the first rtp module to be asked to send a TargetBitrate
203 // message. (No target bitrate with 0bps sent from the second one.)
204 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(bitrate)).Times(1);
205 EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(_)).Times(0);
206
207 payload_router.OnBitrateAllocationUpdated(bitrate);
208}
209
sprang1a646ee2016-12-01 06:34:11 -0800210TEST(PayloadRouterTest, SvcTargetBitrate) {
211 NiceMock<MockRtpRtcp> rtp_1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200212 std::vector<RtpRtcp*> modules = {&rtp_1};
213 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
sprang1a646ee2016-12-01 06:34:11 -0800214 payload_router.SetActive(true);
215
216 BitrateAllocation bitrate;
217 bitrate.SetBitrate(0, 0, 10000);
218 bitrate.SetBitrate(0, 1, 20000);
219 bitrate.SetBitrate(1, 0, 40000);
220 bitrate.SetBitrate(1, 1, 80000);
221
222 EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(bitrate)).Times(1);
223
224 payload_router.OnBitrateAllocationUpdated(bitrate);
225}
226
Åsa Persson4bece9a2017-10-06 10:04:04 +0200227TEST(PayloadRouterTest, InfoMappedToRtpVideoHeader_Vp8) {
228 NiceMock<MockRtpRtcp> rtp1;
229 NiceMock<MockRtpRtcp> rtp2;
230 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
231 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
232 payload_router.SetActive(true);
233
234 EncodedImage encoded_image;
235 encoded_image.rotation_ = kVideoRotation_90;
236 encoded_image.content_type_ = VideoContentType::SCREENSHARE;
237
238 CodecSpecificInfo codec_info;
239 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
240 codec_info.codecType = kVideoCodecVP8;
241 codec_info.codecSpecific.VP8.simulcastIdx = 1;
242 codec_info.codecSpecific.VP8.pictureId = kPictureId;
243 codec_info.codecSpecific.VP8.temporalIdx = kTemporalIdx;
244 codec_info.codecSpecific.VP8.tl0PicIdx = kTl0PicIdx;
245 codec_info.codecSpecific.VP8.keyIdx = kNoKeyIdx;
246 codec_info.codecSpecific.VP8.layerSync = true;
247 codec_info.codecSpecific.VP8.nonReference = true;
248
249 EXPECT_CALL(rtp2, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
250 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
251 Unused, const RTPVideoHeader* header, Unused) {
252 EXPECT_EQ(kVideoRotation_90, header->rotation);
253 EXPECT_EQ(VideoContentType::SCREENSHARE, header->content_type);
254 EXPECT_EQ(1, header->simulcastIdx);
255 EXPECT_EQ(kRtpVideoVp8, header->codec);
256 EXPECT_EQ(kPictureId, header->codecHeader.VP8.pictureId);
257 EXPECT_EQ(kTemporalIdx, header->codecHeader.VP8.temporalIdx);
258 EXPECT_EQ(kTl0PicIdx, header->codecHeader.VP8.tl0PicIdx);
259 EXPECT_EQ(kNoKeyIdx, header->codecHeader.VP8.keyIdx);
260 EXPECT_TRUE(header->codecHeader.VP8.layerSync);
261 EXPECT_TRUE(header->codecHeader.VP8.nonReference);
262 return true;
263 }));
264
265 EXPECT_EQ(
266 EncodedImageCallback::Result::OK,
267 payload_router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
268}
269
270TEST(PayloadRouterTest, InfoMappedToRtpVideoHeader_H264) {
271 NiceMock<MockRtpRtcp> rtp1;
272 std::vector<RtpRtcp*> modules = {&rtp1};
273 PayloadRouter payload_router(modules, {kSsrc1}, kPayloadType, {});
274 payload_router.SetActive(true);
275
276 EncodedImage encoded_image;
277 CodecSpecificInfo codec_info;
278 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
279 codec_info.codecType = kVideoCodecH264;
280 codec_info.codecSpecific.H264.packetization_mode =
281 H264PacketizationMode::SingleNalUnit;
282
283 EXPECT_CALL(rtp1, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
284 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
285 Unused, const RTPVideoHeader* header, Unused) {
286 EXPECT_EQ(0, header->simulcastIdx);
287 EXPECT_EQ(kRtpVideoH264, header->codec);
288 EXPECT_EQ(H264PacketizationMode::SingleNalUnit,
289 header->codecHeader.H264.packetization_mode);
290 return true;
291 }));
292
293 EXPECT_EQ(
294 EncodedImageCallback::Result::OK,
295 payload_router.OnEncodedImage(encoded_image, &codec_info, nullptr).error);
296}
297
298TEST(PayloadRouterTest, CreateWithNoPreviousStates) {
299 NiceMock<MockRtpRtcp> rtp1;
300 NiceMock<MockRtpRtcp> rtp2;
301 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
302 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, {});
303 payload_router.SetActive(true);
304
305 std::map<uint32_t, RtpPayloadState> initial_states =
306 payload_router.GetRtpPayloadStates();
307 EXPECT_EQ(2u, initial_states.size());
308 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
309 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
310}
311
312TEST(PayloadRouterTest, CreateWithPreviousStates) {
313 RtpPayloadState state1;
314 state1.picture_id = kInitialPictureId1;
315 RtpPayloadState state2;
316 state2.picture_id = kInitialPictureId2;
317 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
318 {kSsrc2, state2}};
319
320 NiceMock<MockRtpRtcp> rtp1;
321 NiceMock<MockRtpRtcp> rtp2;
322 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
323 PayloadRouter payload_router(modules, {kSsrc1, kSsrc2}, kPayloadType, states);
324 payload_router.SetActive(true);
325
326 std::map<uint32_t, RtpPayloadState> initial_states =
327 payload_router.GetRtpPayloadStates();
328 EXPECT_EQ(2u, initial_states.size());
329 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
330 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
331}
332
333class PayloadRouterTest : public ::testing::Test {
334 public:
335 explicit PayloadRouterTest(const std::string& field_trials)
336 : override_field_trials_(field_trials) {}
337 virtual ~PayloadRouterTest() {}
338
339 protected:
340 virtual void SetUp() { memset(&codec_info_, 0, sizeof(CodecSpecificInfo)); }
341
342 test::ScopedFieldTrials override_field_trials_;
343 EncodedImage image_;
344 CodecSpecificInfo codec_info_;
345};
346
347class TestWithForcedFallbackDisabled : public PayloadRouterTest {
348 public:
349 TestWithForcedFallbackDisabled()
350 : PayloadRouterTest("WebRTC-VP8-Forced-Fallback-Encoder/Disabled/") {}
351};
352
353class TestWithForcedFallbackEnabled : public PayloadRouterTest {
354 public:
355 TestWithForcedFallbackEnabled()
356 : PayloadRouterTest(
357 "WebRTC-VP8-Forced-Fallback-Encoder/Enabled-1,2,3,4/") {}
358};
359
360TEST_F(TestWithForcedFallbackDisabled, PictureIdIsNotChangedForVp8) {
361 NiceMock<MockRtpRtcp> rtp;
362 std::vector<RtpRtcp*> modules = {&rtp};
363 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {});
364 router.SetActive(true);
365
366 codec_info_.codecType = kVideoCodecVP8;
367 codec_info_.codecSpecific.VP8.pictureId = kPictureId;
368
369 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
370 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
371 Unused, const RTPVideoHeader* header, Unused) {
372 EXPECT_EQ(kRtpVideoVp8, header->codec);
373 EXPECT_EQ(kPictureId, header->codecHeader.VP8.pictureId);
374 return true;
375 }));
376
377 EXPECT_EQ(EncodedImageCallback::Result::OK,
378 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
379}
380
381TEST_F(TestWithForcedFallbackEnabled, PictureIdIsSetForVp8) {
382 RtpPayloadState state1;
383 state1.picture_id = kInitialPictureId1;
384 RtpPayloadState state2;
385 state2.picture_id = kInitialPictureId2;
386 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
387 {kSsrc2, state2}};
388
389 NiceMock<MockRtpRtcp> rtp1;
390 NiceMock<MockRtpRtcp> rtp2;
391 std::vector<RtpRtcp*> modules = {&rtp1, &rtp2};
392 PayloadRouter router(modules, {kSsrc1, kSsrc2}, kPayloadType, states);
393 router.SetActive(true);
394
395 // OnEncodedImage, simulcastIdx: 0.
396 codec_info_.codecType = kVideoCodecVP8;
397 codec_info_.codecSpecific.VP8.pictureId = kPictureId;
398 codec_info_.codecSpecific.VP8.simulcastIdx = 0;
399
400 EXPECT_CALL(rtp1, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
401 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
402 Unused, const RTPVideoHeader* header, Unused) {
403 EXPECT_EQ(kRtpVideoVp8, header->codec);
404 EXPECT_EQ(kInitialPictureId1, header->codecHeader.VP8.pictureId);
405 return true;
406 }));
407
408 EXPECT_EQ(EncodedImageCallback::Result::OK,
409 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
410
411 // OnEncodedImage, simulcastIdx: 1.
412 codec_info_.codecSpecific.VP8.pictureId = kPictureId;
413 codec_info_.codecSpecific.VP8.simulcastIdx = 1;
414
415 EXPECT_CALL(rtp2, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
416 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
417 Unused, const RTPVideoHeader* header, Unused) {
418 EXPECT_EQ(kRtpVideoVp8, header->codec);
419 EXPECT_EQ(kInitialPictureId2, header->codecHeader.VP8.pictureId);
420 return true;
421 }));
422
423 EXPECT_EQ(EncodedImageCallback::Result::OK,
424 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
425
426 // State should hold next picture id to use.
427 states = router.GetRtpPayloadStates();
428 EXPECT_EQ(2u, states.size());
429 EXPECT_EQ(kInitialPictureId1 + 1, states[kSsrc1].picture_id);
430 EXPECT_EQ(kInitialPictureId2 + 1, states[kSsrc2].picture_id);
431}
432
433TEST_F(TestWithForcedFallbackEnabled, PictureIdWraps) {
434 RtpPayloadState state1;
435 state1.picture_id = kMaxTwoBytePictureId;
436
437 NiceMock<MockRtpRtcp> rtp;
438 std::vector<RtpRtcp*> modules = {&rtp};
439 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {{kSsrc1, state1}});
440 router.SetActive(true);
441
442 codec_info_.codecType = kVideoCodecVP8;
443 codec_info_.codecSpecific.VP8.pictureId = kPictureId;
444
445 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
446 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
447 Unused, const RTPVideoHeader* header, Unused) {
448 EXPECT_EQ(kRtpVideoVp8, header->codec);
449 EXPECT_EQ(kMaxTwoBytePictureId, header->codecHeader.VP8.pictureId);
450 return true;
451 }));
452
453 EXPECT_EQ(EncodedImageCallback::Result::OK,
454 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
455
456 // State should hold next picture id to use.
457 std::map<uint32_t, RtpPayloadState> states = router.GetRtpPayloadStates();
458 EXPECT_EQ(1u, states.size());
459 EXPECT_EQ(0, states[kSsrc1].picture_id); // Wrapped.
460}
461
462TEST_F(TestWithForcedFallbackEnabled, PictureIdIsNotSetIfNoPictureId) {
463 NiceMock<MockRtpRtcp> rtp;
464 std::vector<RtpRtcp*> modules = {&rtp};
465 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {});
466 router.SetActive(true);
467
468 codec_info_.codecType = kVideoCodecVP8;
469 codec_info_.codecSpecific.VP8.pictureId = kNoPictureId;
470
471 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
472 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
473 Unused, const RTPVideoHeader* header, Unused) {
474 EXPECT_EQ(kRtpVideoVp8, header->codec);
475 EXPECT_EQ(kNoPictureId, header->codecHeader.VP8.pictureId);
476 return true;
477 }));
478
479 EXPECT_EQ(EncodedImageCallback::Result::OK,
480 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
481}
482
483TEST_F(TestWithForcedFallbackEnabled, PictureIdIsNotSetForVp9) {
484 NiceMock<MockRtpRtcp> rtp;
485 std::vector<RtpRtcp*> modules = {&rtp};
486 PayloadRouter router(modules, {kSsrc1}, kPayloadType, {});
487 router.SetActive(true);
488
489 codec_info_.codecType = kVideoCodecVP9;
490 codec_info_.codecSpecific.VP9.picture_id = kPictureId;
491
492 EXPECT_CALL(rtp, SendOutgoingData(_, _, _, _, _, _, nullptr, _, _))
493 .WillOnce(Invoke([](Unused, Unused, Unused, Unused, Unused, Unused,
494 Unused, const RTPVideoHeader* header, Unused) {
495 EXPECT_EQ(kRtpVideoVp9, header->codec);
496 EXPECT_EQ(kPictureId, header->codecHeader.VP9.picture_id);
497 return true;
498 }));
499
500 EXPECT_EQ(EncodedImageCallback::Result::OK,
501 router.OnEncodedImage(image_, &codec_info_, nullptr).error);
502}
503
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000504} // namespace webrtc