blob: d83e81e5cccc5d7a619b9919a399d2a3b41fda6a [file] [log] [blame]
johan62d02c32017-01-24 04:38:27 -08001/*
2 * Copyright 2017 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 "video/rtp_video_stream_receiver.h"
johan62d02c32017-01-24 04:38:27 -080012
Mirko Bonadei317a1f02019-09-17 17:06:18 +020013#include <memory>
14
Johannes Krond51ec582019-04-15 13:32:41 +020015#include "api/video/video_codec_type.h"
16#include "api/video/video_frame_type.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "common_video/h264/h264_common.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "media/base/media_constants.h"
Johannes Krond51ec582019-04-15 13:32:41 +020019#include "modules/rtp_rtcp/source/rtp_format.h"
Danil Chapovalov51bf2002019-10-11 10:53:27 +020020#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
philipeldabfcae2018-09-25 12:54:37 +020021#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
22#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
Johannes Krond51ec582019-04-15 13:32:41 +020023#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Johannes Krond51ec582019-04-15 13:32:41 +020025#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "modules/utility/include/process_thread.h"
27#include "modules/video_coding/frame_object.h"
28#include "modules/video_coding/include/video_coding_defines.h"
29#include "modules/video_coding/packet.h"
30#include "modules/video_coding/rtp_frame_reference_finder.h"
Steve Anton10542f22019-01-11 09:11:00 -080031#include "rtc_base/byte_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020033#include "system_wrappers/include/clock.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020034#include "system_wrappers/include/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020035#include "test/field_trial.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020036#include "test/gmock.h"
37#include "test/gtest.h"
johan62d02c32017-01-24 04:38:27 -080038
philipeldabfcae2018-09-25 12:54:37 +020039using ::testing::_;
40using ::testing::Invoke;
Chen Xingf00bf422019-06-20 10:05:55 +020041using ::testing::SizeIs;
Elad Alonccb9b752019-02-19 13:01:31 +010042using ::testing::Values;
johan62d02c32017-01-24 04:38:27 -080043
44namespace webrtc {
45
46namespace {
47
johan62d02c32017-01-24 04:38:27 -080048const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
49
50class MockTransport : public Transport {
51 public:
52 MOCK_METHOD3(SendRtp,
53 bool(const uint8_t* packet,
54 size_t length,
55 const PacketOptions& options));
56 MOCK_METHOD2(SendRtcp, bool(const uint8_t* packet, size_t length));
57};
58
59class MockNackSender : public NackSender {
60 public:
61 MOCK_METHOD1(SendNack, void(const std::vector<uint16_t>& sequence_numbers));
Elad Alonef09c5b2019-05-31 13:25:50 +020062 MOCK_METHOD2(SendNack,
63 void(const std::vector<uint16_t>& sequence_numbers,
64 bool buffering_allowed));
johan62d02c32017-01-24 04:38:27 -080065};
66
67class MockKeyFrameRequestSender : public KeyFrameRequestSender {
68 public:
69 MOCK_METHOD0(RequestKeyFrame, void());
70};
71
72class MockOnCompleteFrameCallback
73 : public video_coding::OnCompleteFrameCallback {
74 public:
75 MockOnCompleteFrameCallback() : buffer_(rtc::ByteBuffer::ORDER_NETWORK) {}
76
philipele7c891f2018-02-22 14:35:06 +010077 MOCK_METHOD1(DoOnCompleteFrame, void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080078 MOCK_METHOD1(DoOnCompleteFrameFailNullptr,
philipele7c891f2018-02-22 14:35:06 +010079 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080080 MOCK_METHOD1(DoOnCompleteFrameFailLength,
philipele7c891f2018-02-22 14:35:06 +010081 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080082 MOCK_METHOD1(DoOnCompleteFrameFailBitstream,
philipele7c891f2018-02-22 14:35:06 +010083 void(video_coding::EncodedFrame* frame));
84 void OnCompleteFrame(std::unique_ptr<video_coding::EncodedFrame> frame) {
johan62d02c32017-01-24 04:38:27 -080085 if (!frame) {
86 DoOnCompleteFrameFailNullptr(nullptr);
87 return;
88 }
89 EXPECT_EQ(buffer_.Length(), frame->size());
90 if (buffer_.Length() != frame->size()) {
91 DoOnCompleteFrameFailLength(frame.get());
92 return;
93 }
Niels Möllerf0eee002018-11-28 16:31:29 +010094 if (frame->size() != buffer_.Length() ||
Niels Möller9c843902019-01-11 10:21:35 +010095 memcmp(buffer_.Data(), frame->data(), buffer_.Length()) != 0) {
johan62d02c32017-01-24 04:38:27 -080096 DoOnCompleteFrameFailBitstream(frame.get());
97 return;
98 }
99 DoOnCompleteFrame(frame.get());
100 }
Johannes Krond51ec582019-04-15 13:32:41 +0200101
102 void ClearExpectedBitstream() { buffer_.Clear(); }
103
johan62d02c32017-01-24 04:38:27 -0800104 void AppendExpectedBitstream(const uint8_t data[], size_t size_in_bytes) {
105 // TODO(Johan): Let rtc::ByteBuffer handle uint8_t* instead of char*.
106 buffer_.WriteBytes(reinterpret_cast<const char*>(data), size_in_bytes);
107 }
108 rtc::ByteBufferWriter buffer_;
109};
110
eladalonc0d481a2017-08-02 07:39:07 -0700111class MockRtpPacketSink : public RtpPacketSinkInterface {
112 public:
113 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&));
114};
115
116constexpr uint32_t kSsrc = 111;
117constexpr uint16_t kSequenceNumber = 222;
118std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(
119 uint32_t ssrc = kSsrc,
120 uint16_t sequence_number = kSequenceNumber) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200121 auto packet = std::make_unique<RtpPacketReceived>();
eladalonc0d481a2017-08-02 07:39:07 -0700122 packet->SetSsrc(ssrc);
123 packet->SetSequenceNumber(sequence_number);
124 return packet;
125}
126
127MATCHER_P(SamePacketAs, other, "") {
128 return arg.Ssrc() == other.Ssrc() &&
129 arg.SequenceNumber() == other.SequenceNumber();
130}
131
johan62d02c32017-01-24 04:38:27 -0800132} // namespace
133
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200134class RtpVideoStreamReceiverTest : public ::testing::Test {
johan62d02c32017-01-24 04:38:27 -0800135 public:
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100136 RtpVideoStreamReceiverTest() : RtpVideoStreamReceiverTest("") {}
137 explicit RtpVideoStreamReceiverTest(std::string field_trials)
138 : override_field_trials_(field_trials),
139 config_(CreateConfig()),
johan62d02c32017-01-24 04:38:27 -0800140 process_thread_(ProcessThread::Create("TestThread")) {}
141
142 void SetUp() {
nisseca5706d2017-09-11 02:32:16 -0700143 rtp_receive_statistics_ =
Niels Möller0d210ee2019-08-07 16:16:45 +0200144 ReceiveStatistics::Create(Clock::GetRealTimeClock());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200145 rtp_video_stream_receiver_ = std::make_unique<RtpVideoStreamReceiver>(
Niels Möller60f4e292019-05-20 11:06:33 +0200146 Clock::GetRealTimeClock(), &mock_transport_, nullptr, nullptr, &config_,
147 rtp_receive_statistics_.get(), nullptr, process_thread_.get(),
Niels Möller2f5554d2019-05-29 13:35:14 +0200148 &mock_nack_sender_, &mock_key_frame_request_sender_,
149 &mock_on_complete_frame_callback_, nullptr);
johan62d02c32017-01-24 04:38:27 -0800150 }
151
Niels Möller125b5d62019-03-11 16:11:07 +0100152 RTPVideoHeader GetDefaultH264VideoHeader() {
153 RTPVideoHeader video_header;
154 video_header.codec = kVideoCodecH264;
155 video_header.video_type_header.emplace<RTPVideoHeaderH264>();
156 return video_header;
johan62d02c32017-01-24 04:38:27 -0800157 }
158
159 // TODO(Johan): refactor h264_sps_pps_tracker_unittests.cc to avoid duplicate
160 // code.
Niels Möller125b5d62019-03-11 16:11:07 +0100161 void AddSps(RTPVideoHeader* video_header,
philipel83c97da2017-06-21 07:22:40 -0700162 uint8_t sps_id,
163 std::vector<uint8_t>* data) {
johan62d02c32017-01-24 04:38:27 -0800164 NaluInfo info;
165 info.type = H264::NaluType::kSps;
166 info.sps_id = sps_id;
167 info.pps_id = -1;
johan62d02c32017-01-24 04:38:27 -0800168 data->push_back(H264::NaluType::kSps);
169 data->push_back(sps_id);
Niels Möller125b5d62019-03-11 16:11:07 +0100170 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200171 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800172 }
173
Niels Möller125b5d62019-03-11 16:11:07 +0100174 void AddPps(RTPVideoHeader* video_header,
philipel83c97da2017-06-21 07:22:40 -0700175 uint8_t sps_id,
176 uint8_t pps_id,
johan62d02c32017-01-24 04:38:27 -0800177 std::vector<uint8_t>* data) {
178 NaluInfo info;
179 info.type = H264::NaluType::kPps;
180 info.sps_id = sps_id;
181 info.pps_id = pps_id;
johan62d02c32017-01-24 04:38:27 -0800182 data->push_back(H264::NaluType::kPps);
183 data->push_back(pps_id);
Niels Möller125b5d62019-03-11 16:11:07 +0100184 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200185 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800186 }
187
Niels Möller125b5d62019-03-11 16:11:07 +0100188 void AddIdr(RTPVideoHeader* video_header, int pps_id) {
johan62d02c32017-01-24 04:38:27 -0800189 NaluInfo info;
190 info.type = H264::NaluType::kIdr;
191 info.sps_id = -1;
192 info.pps_id = pps_id;
Niels Möller125b5d62019-03-11 16:11:07 +0100193 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200194 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800195 }
196
197 protected:
198 static VideoReceiveStream::Config CreateConfig() {
199 VideoReceiveStream::Config config(nullptr);
200 config.rtp.remote_ssrc = 1111;
201 config.rtp.local_ssrc = 2222;
202 return config;
203 }
204
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100205 const webrtc::test::ScopedFieldTrials override_field_trials_;
johan62d02c32017-01-24 04:38:27 -0800206 VideoReceiveStream::Config config_;
207 MockNackSender mock_nack_sender_;
Niels Möller2f5554d2019-05-29 13:35:14 +0200208 MockKeyFrameRequestSender mock_key_frame_request_sender_;
johan62d02c32017-01-24 04:38:27 -0800209 MockTransport mock_transport_;
210 MockOnCompleteFrameCallback mock_on_complete_frame_callback_;
johan62d02c32017-01-24 04:38:27 -0800211 std::unique_ptr<ProcessThread> process_thread_;
nisseca5706d2017-09-11 02:32:16 -0700212 std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
nisseb1f2ff92017-06-09 04:01:55 -0700213 std::unique_ptr<RtpVideoStreamReceiver> rtp_video_stream_receiver_;
johan62d02c32017-01-24 04:38:27 -0800214};
215
Johannes Krond51ec582019-04-15 13:32:41 +0200216TEST_F(RtpVideoStreamReceiverTest, CacheColorSpaceFromLastPacketOfKeyframe) {
217 // Test that color space is cached from the last packet of a key frame and
218 // that it's not reset by padding packets without color space.
219 constexpr int kPayloadType = 99;
220 const ColorSpace kColorSpace(
221 ColorSpace::PrimaryID::kFILM, ColorSpace::TransferID::kBT2020_12,
222 ColorSpace::MatrixID::kBT2020_NCL, ColorSpace::RangeID::kFull);
223 const std::vector<uint8_t> kKeyFramePayload = {0, 1, 2, 3, 4, 5,
224 6, 7, 8, 9, 10};
225 const std::vector<uint8_t> kDeltaFramePayload = {0, 1, 2, 3, 4};
226
227 // Anonymous helper class that generates received packets.
228 class {
229 public:
230 void SetPayload(const std::vector<uint8_t>& payload,
231 VideoFrameType video_frame_type) {
232 video_frame_type_ = video_frame_type;
233 RtpPacketizer::PayloadSizeLimits pay_load_size_limits;
234 // Reduce max payload length to make sure the key frame generates two
235 // packets.
236 pay_load_size_limits.max_payload_len = 8;
Johannes Krond51ec582019-04-15 13:32:41 +0200237 RTPVideoHeaderVP9 rtp_video_header_vp9;
238 rtp_video_header_vp9.InitRTPVideoHeaderVP9();
239 rtp_video_header_vp9.inter_pic_predicted =
240 (video_frame_type == VideoFrameType::kVideoFrameDelta);
Danil Chapovalov51bf2002019-10-11 10:53:27 +0200241 rtp_packetizer_ = std::make_unique<RtpPacketizerVp9>(
242 payload, pay_load_size_limits, rtp_video_header_vp9);
Johannes Krond51ec582019-04-15 13:32:41 +0200243 }
244
245 size_t NumPackets() { return rtp_packetizer_->NumPackets(); }
246 void SetColorSpace(const ColorSpace& color_space) {
247 color_space_ = color_space;
248 }
249
250 RtpPacketReceived NextPacket() {
251 RtpHeaderExtensionMap extension_map;
252 extension_map.Register<ColorSpaceExtension>(1);
253 RtpPacketToSend packet_to_send(&extension_map);
254 packet_to_send.SetSequenceNumber(sequence_number_++);
255 packet_to_send.SetSsrc(kSsrc);
256 packet_to_send.SetPayloadType(kPayloadType);
257 bool include_color_space =
258 (rtp_packetizer_->NumPackets() == 1u &&
259 video_frame_type_ == VideoFrameType::kVideoFrameKey);
260 if (include_color_space) {
261 EXPECT_TRUE(
262 packet_to_send.SetExtension<ColorSpaceExtension>(color_space_));
263 }
264 rtp_packetizer_->NextPacket(&packet_to_send);
265
266 RtpPacketReceived received_packet(&extension_map);
267 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
268 return received_packet;
269 }
270
271 private:
272 uint16_t sequence_number_ = 0;
273 VideoFrameType video_frame_type_;
274 ColorSpace color_space_;
275 std::unique_ptr<RtpPacketizer> rtp_packetizer_;
276 } received_packet_generator;
277 received_packet_generator.SetColorSpace(kColorSpace);
278
279 // Prepare the receiver for VP9.
280 VideoCodec codec;
281 codec.plType = kPayloadType;
282 codec.codecType = kVideoCodecVP9;
283 std::map<std::string, std::string> codec_params;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200284 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
285 /*raw_payload=*/false);
Johannes Krond51ec582019-04-15 13:32:41 +0200286
287 // Generate key frame packets.
288 received_packet_generator.SetPayload(kKeyFramePayload,
289 VideoFrameType::kVideoFrameKey);
290 EXPECT_EQ(received_packet_generator.NumPackets(), 2u);
291 RtpPacketReceived key_frame_packet1 = received_packet_generator.NextPacket();
292 RtpPacketReceived key_frame_packet2 = received_packet_generator.NextPacket();
293
294 // Generate delta frame packet.
295 received_packet_generator.SetPayload(kDeltaFramePayload,
296 VideoFrameType::kVideoFrameDelta);
297 EXPECT_EQ(received_packet_generator.NumPackets(), 1u);
298 RtpPacketReceived delta_frame_packet = received_packet_generator.NextPacket();
299
300 rtp_video_stream_receiver_->StartReceive();
301 mock_on_complete_frame_callback_.AppendExpectedBitstream(
302 kKeyFramePayload.data(), kKeyFramePayload.size());
303
304 // Send the key frame and expect a callback with color space information.
305 EXPECT_FALSE(key_frame_packet1.GetExtension<ColorSpaceExtension>());
306 EXPECT_TRUE(key_frame_packet2.GetExtension<ColorSpaceExtension>());
307 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
308 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
309 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
310 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
311 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
312 }));
313 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet2);
314 // Resend the first key frame packet to simulate padding for example.
315 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
316
317 mock_on_complete_frame_callback_.ClearExpectedBitstream();
318 mock_on_complete_frame_callback_.AppendExpectedBitstream(
319 kDeltaFramePayload.data(), kDeltaFramePayload.size());
320
321 // Expect delta frame to have color space set even though color space not
322 // included in the RTP packet.
323 EXPECT_FALSE(delta_frame_packet.GetExtension<ColorSpaceExtension>());
324 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
325 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
326 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
327 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
328 }));
329 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
330}
331
nisseb1f2ff92017-06-09 04:01:55 -0700332TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200333 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100334 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800335 const std::vector<uint8_t> data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200336 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100337 video_header.is_first_packet_in_frame = true;
338 video_header.is_last_packet_in_frame = true;
339 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200340 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800341 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
342 data.size());
343 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200344 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
345 video_header);
johan62d02c32017-01-24 04:38:27 -0800346}
347
philipeld8f6c162018-01-19 14:41:41 +0100348TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
349 const uint8_t kRedPayloadType = 125;
350 VideoCodec codec;
351 codec.plType = kRedPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200352 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200353 const std::vector<uint8_t> data({
354 0x80, // RTP version.
355 kRedPayloadType, // Payload type.
356 0, 0, 0, 0, 0, 0, // Don't care.
357 0, 0, 0x4, 0x57, // SSRC
358 kRedPayloadType, // RED header.
359 0, 0, 0, 0, 0 // Don't care.
360 });
philipeld8f6c162018-01-19 14:41:41 +0100361 RtpPacketReceived packet;
362 EXPECT_TRUE(packet.Parse(data.data(), data.size()));
363 rtp_video_stream_receiver_->StartReceive();
364 rtp_video_stream_receiver_->OnRtpPacket(packet);
365}
366
Danil Chapovalova715f282018-07-11 17:50:41 +0200367TEST_F(RtpVideoStreamReceiverTest,
368 DropsPacketWithRedPayloadTypeAndEmptyPayload) {
369 const uint8_t kRedPayloadType = 125;
370 config_.rtp.red_payload_type = kRedPayloadType;
371 SetUp(); // re-create rtp_video_stream_receiver with red payload type.
372 // clang-format off
373 const uint8_t data[] = {
374 0x80, // RTP version.
375 kRedPayloadType, // Payload type.
376 0, 0, 0, 0, 0, 0, // Don't care.
377 0, 0, 0x4, 0x57, // SSRC
378 // Empty rtp payload.
379 };
380 // clang-format on
381 RtpPacketReceived packet;
382 // Manually convert to CopyOnWriteBuffer to be sure capacity == size
383 // and asan bot can catch read buffer overflow.
384 EXPECT_TRUE(packet.Parse(rtc::CopyOnWriteBuffer(data)));
385 rtp_video_stream_receiver_->StartReceive();
386 rtp_video_stream_receiver_->OnRtpPacket(packet);
387 // Expect asan doesn't find anything.
388}
389
nisseb1f2ff92017-06-09 04:01:55 -0700390TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrameBitstreamError) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200391 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100392 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800393 const std::vector<uint8_t> data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200394 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100395 video_header.is_first_packet_in_frame = true;
396 video_header.is_last_packet_in_frame = true;
397 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200398 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800399 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
400 mock_on_complete_frame_callback_.AppendExpectedBitstream(
401 expected_bitsteam, sizeof(expected_bitsteam));
402 EXPECT_CALL(mock_on_complete_frame_callback_,
403 DoOnCompleteFrameFailBitstream(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200404 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
405 video_header);
johan62d02c32017-01-24 04:38:27 -0800406}
407
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100408class RtpVideoStreamReceiverTestH264
409 : public RtpVideoStreamReceiverTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200410 public ::testing::WithParamInterface<std::string> {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100411 protected:
412 RtpVideoStreamReceiverTestH264() : RtpVideoStreamReceiverTest(GetParam()) {}
413};
414
Elad Alonccb9b752019-02-19 13:01:31 +0100415INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
416 RtpVideoStreamReceiverTestH264,
417 Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100418
419TEST_P(RtpVideoStreamReceiverTestH264, InBandSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800420 std::vector<uint8_t> sps_data;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200421 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100422 RTPVideoHeader sps_video_header = GetDefaultH264VideoHeader();
423 AddSps(&sps_video_header, 0, &sps_data);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200424 rtp_packet.SetSequenceNumber(0);
Niels Möller125b5d62019-03-11 16:11:07 +0100425 sps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200426 sps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800427 mock_on_complete_frame_callback_.AppendExpectedBitstream(
428 kH264StartCode, sizeof(kH264StartCode));
429 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
430 sps_data.size());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200431 rtp_video_stream_receiver_->OnReceivedPayloadData(sps_data, rtp_packet,
432 sps_video_header);
johan62d02c32017-01-24 04:38:27 -0800433
434 std::vector<uint8_t> pps_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100435 RTPVideoHeader pps_video_header = GetDefaultH264VideoHeader();
436 AddPps(&pps_video_header, 0, 1, &pps_data);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200437 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100438 pps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200439 pps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800440 mock_on_complete_frame_callback_.AppendExpectedBitstream(
441 kH264StartCode, sizeof(kH264StartCode));
442 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
443 pps_data.size());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200444 rtp_video_stream_receiver_->OnReceivedPayloadData(pps_data, rtp_packet,
445 pps_video_header);
johan62d02c32017-01-24 04:38:27 -0800446
447 std::vector<uint8_t> idr_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100448 RTPVideoHeader idr_video_header = GetDefaultH264VideoHeader();
449 AddIdr(&idr_video_header, 1);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200450 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100451 idr_video_header.is_first_packet_in_frame = true;
452 idr_video_header.is_last_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200453 idr_video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800454 idr_data.insert(idr_data.end(), {0x65, 1, 2, 3});
455 mock_on_complete_frame_callback_.AppendExpectedBitstream(
456 kH264StartCode, sizeof(kH264StartCode));
457 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
458 idr_data.size());
459 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200460 rtp_video_stream_receiver_->OnReceivedPayloadData(idr_data, rtp_packet,
461 idr_video_header);
johan62d02c32017-01-24 04:38:27 -0800462}
463
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100464TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800465 constexpr int kPayloadType = 99;
466 VideoCodec codec;
467 codec.plType = kPayloadType;
468 std::map<std::string, std::string> codec_params;
469 // Example parameter sets from https://tools.ietf.org/html/rfc3984#section-8.2
470 // .
471 codec_params.insert(
472 {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="});
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200473 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
474 /*raw_payload=*/false);
johan62d02c32017-01-24 04:38:27 -0800475 const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
476 0x53, 0x05, 0x89, 0x88};
477 mock_on_complete_frame_callback_.AppendExpectedBitstream(
478 kH264StartCode, sizeof(kH264StartCode));
479 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_sps,
480 sizeof(binary_sps));
481 const uint8_t binary_pps[] = {0x68, 0xc9, 0x63, 0x88};
482 mock_on_complete_frame_callback_.AppendExpectedBitstream(
483 kH264StartCode, sizeof(kH264StartCode));
484 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_pps,
485 sizeof(binary_pps));
486
487 std::vector<uint8_t> data;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200488 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100489 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
490 AddIdr(&video_header, 0);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200491 rtp_packet.SetPayloadType(kPayloadType);
492 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100493 video_header.is_first_packet_in_frame = true;
494 video_header.is_last_packet_in_frame = true;
495 video_header.codec = kVideoCodecH264;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200496 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800497 data.insert(data.end(), {1, 2, 3});
498 mock_on_complete_frame_callback_.AppendExpectedBitstream(
499 kH264StartCode, sizeof(kH264StartCode));
500 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
501 data.size());
502 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200503 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
504 video_header);
johan62d02c32017-01-24 04:38:27 -0800505}
506
nisseb1f2ff92017-06-09 04:01:55 -0700507TEST_F(RtpVideoStreamReceiverTest, PaddingInMediaStream) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200508 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100509 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
philipel54ca9192017-03-21 05:45:18 -0700510 std::vector<uint8_t> data;
511 data.insert(data.end(), {1, 2, 3});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200512 rtp_packet.SetPayloadType(99);
513 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100514 video_header.is_first_packet_in_frame = true;
515 video_header.is_last_packet_in_frame = true;
516 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200517 video_header.frame_type = VideoFrameType::kVideoFrameKey;
philipel54ca9192017-03-21 05:45:18 -0700518 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
519 data.size());
520
521 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200522 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
523 video_header);
philipel54ca9192017-03-21 05:45:18 -0700524
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200525 rtp_packet.SetSequenceNumber(3);
526 rtp_video_stream_receiver_->OnReceivedPayloadData({}, rtp_packet,
527 video_header);
philipel54ca9192017-03-21 05:45:18 -0700528
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200529 rtp_packet.SetSequenceNumber(4);
philipel54ca9192017-03-21 05:45:18 -0700530 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möllerabbc50e2019-04-24 09:41:16 +0200531 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200532 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
533 video_header);
philipel54ca9192017-03-21 05:45:18 -0700534
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200535 rtp_packet.SetSequenceNumber(6);
536 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
537 video_header);
philipel54ca9192017-03-21 05:45:18 -0700538
539 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200540 rtp_packet.SetSequenceNumber(5);
541 rtp_video_stream_receiver_->OnReceivedPayloadData({}, rtp_packet,
542 video_header);
philipel54ca9192017-03-21 05:45:18 -0700543}
544
nisseb1f2ff92017-06-09 04:01:55 -0700545TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeIfFirstFrameIsDelta) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200546 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100547 RTPVideoHeader video_header;
philipel2c53b132017-05-16 08:06:30 -0700548 const std::vector<uint8_t> data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200549 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100550 video_header.is_first_packet_in_frame = true;
551 video_header.is_last_packet_in_frame = true;
552 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200553 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Niels Möller2f5554d2019-05-29 13:35:14 +0200554 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200555 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
556 video_header);
philipel2c53b132017-05-16 08:06:30 -0700557}
558
Johannes Kronbd3f3052019-08-01 15:45:54 +0200559TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeWhenPacketBufferGetsFull) {
560 constexpr int kPacketBufferMaxSize = 2048;
561
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200562 RtpPacketReceived rtp_packet;
Johannes Kronbd3f3052019-08-01 15:45:54 +0200563 RTPVideoHeader video_header;
564 const std::vector<uint8_t> data({1, 2, 3, 4});
565 video_header.is_first_packet_in_frame = true;
566 // Incomplete frames so that the packet buffer is filling up.
567 video_header.is_last_packet_in_frame = false;
568 video_header.codec = kVideoCodecGeneric;
569 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
570 uint16_t start_sequence_number = 1234;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200571 rtp_packet.SetSequenceNumber(start_sequence_number);
572 while (rtp_packet.SequenceNumber() - start_sequence_number <
Johannes Kronbd3f3052019-08-01 15:45:54 +0200573 kPacketBufferMaxSize) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200574 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
575 video_header);
576 rtp_packet.SetSequenceNumber(rtp_packet.SequenceNumber() + 2);
Johannes Kronbd3f3052019-08-01 15:45:54 +0200577 }
578
579 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200580 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
581 video_header);
Johannes Kronbd3f3052019-08-01 15:45:54 +0200582}
583
eladalonc0d481a2017-08-02 07:39:07 -0700584TEST_F(RtpVideoStreamReceiverTest, SecondarySinksGetRtpNotifications) {
585 rtp_video_stream_receiver_->StartReceive();
586
587 MockRtpPacketSink secondary_sink_1;
588 MockRtpPacketSink secondary_sink_2;
589
590 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_1);
591 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_2);
592
593 auto rtp_packet = CreateRtpPacketReceived();
594 EXPECT_CALL(secondary_sink_1, OnRtpPacket(SamePacketAs(*rtp_packet)));
595 EXPECT_CALL(secondary_sink_2, OnRtpPacket(SamePacketAs(*rtp_packet)));
596
597 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
598
599 // Test tear-down.
600 rtp_video_stream_receiver_->StopReceive();
601 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_1);
602 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_2);
603}
604
605TEST_F(RtpVideoStreamReceiverTest, RemovedSecondarySinksGetNoRtpNotifications) {
606 rtp_video_stream_receiver_->StartReceive();
607
608 MockRtpPacketSink secondary_sink;
609
610 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
611 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
612
613 auto rtp_packet = CreateRtpPacketReceived();
614
615 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
616
617 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
618
619 // Test tear-down.
620 rtp_video_stream_receiver_->StopReceive();
621}
622
623TEST_F(RtpVideoStreamReceiverTest,
624 OnlyRemovedSecondarySinksExcludedFromNotifications) {
625 rtp_video_stream_receiver_->StartReceive();
626
627 MockRtpPacketSink kept_secondary_sink;
628 MockRtpPacketSink removed_secondary_sink;
629
630 rtp_video_stream_receiver_->AddSecondarySink(&kept_secondary_sink);
631 rtp_video_stream_receiver_->AddSecondarySink(&removed_secondary_sink);
632 rtp_video_stream_receiver_->RemoveSecondarySink(&removed_secondary_sink);
633
634 auto rtp_packet = CreateRtpPacketReceived();
635 EXPECT_CALL(kept_secondary_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
636
637 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
638
639 // Test tear-down.
640 rtp_video_stream_receiver_->StopReceive();
641 rtp_video_stream_receiver_->RemoveSecondarySink(&kept_secondary_sink);
642}
643
644TEST_F(RtpVideoStreamReceiverTest,
645 SecondariesOfNonStartedStreamGetNoNotifications) {
646 // Explicitly showing that the stream is not in the |started| state,
647 // regardless of whether streams start out |started| or |stopped|.
648 rtp_video_stream_receiver_->StopReceive();
649
650 MockRtpPacketSink secondary_sink;
651 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
652
653 auto rtp_packet = CreateRtpPacketReceived();
654 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
655
656 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
657
658 // Test tear-down.
659 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
660}
661
Elad Alonccb9b752019-02-19 13:01:31 +0100662class RtpVideoStreamReceiverGenericDescriptorTest
663 : public RtpVideoStreamReceiverTest,
664 public ::testing::WithParamInterface<int> {
665 public:
666 void RegisterRtpGenericFrameDescriptorExtension(
667 RtpHeaderExtensionMap* extension_map,
668 int version) {
669 constexpr int kId00 = 5;
670 constexpr int kId01 = 6;
671 switch (version) {
672 case 0:
673 extension_map->Register<RtpGenericFrameDescriptorExtension00>(kId00);
674 return;
675 case 1:
676 extension_map->Register<RtpGenericFrameDescriptorExtension01>(kId01);
677 return;
678 }
679 RTC_NOTREACHED();
680 }
681
682 bool SetExtensionRtpGenericFrameDescriptorExtension(
683 const RtpGenericFrameDescriptor& generic_descriptor,
684 RtpPacketReceived* rtp_packet,
685 int version) {
686 switch (version) {
687 case 0:
688 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension00>(
689 generic_descriptor);
690 case 1:
691 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension01>(
692 generic_descriptor);
693 }
694 RTC_NOTREACHED();
695 return false;
696 }
697};
698
Mirko Bonadei1b575412019-09-23 08:34:50 +0200699INSTANTIATE_TEST_SUITE_P(All,
Elad Alonccb9b752019-02-19 13:01:31 +0100700 RtpVideoStreamReceiverGenericDescriptorTest,
701 Values(0, 1));
702
703TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
704 ParseGenericDescriptorOnePacket) {
705 const int version = GetParam();
706
philipeldabfcae2018-09-25 12:54:37 +0200707 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
708 const int kPayloadType = 123;
709 const int kSpatialIndex = 1;
710
711 VideoCodec codec;
712 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200713 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200714 rtp_video_stream_receiver_->StartReceive();
715
716 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100717 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200718 RtpPacketReceived rtp_packet(&extension_map);
719
720 RtpGenericFrameDescriptor generic_descriptor;
721 generic_descriptor.SetFirstPacketInSubFrame(true);
722 generic_descriptor.SetLastPacketInSubFrame(true);
philipeldabfcae2018-09-25 12:54:37 +0200723 generic_descriptor.SetFrameId(100);
724 generic_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
725 generic_descriptor.AddFrameDependencyDiff(90);
726 generic_descriptor.AddFrameDependencyDiff(80);
Elad Alonccb9b752019-02-19 13:01:31 +0100727 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
728 generic_descriptor, &rtp_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200729
730 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
731 memcpy(payload, data.data(), data.size());
732 // The first byte is the header, so we ignore the first byte of |data|.
733 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
734 data.size() - 1);
735
736 rtp_packet.SetMarker(true);
737 rtp_packet.SetPayloadType(kPayloadType);
738 rtp_packet.SetSequenceNumber(1);
739
740 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
741 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
742 EXPECT_EQ(frame->num_references, 2U);
743 EXPECT_EQ(frame->references[0], frame->id.picture_id - 90);
744 EXPECT_EQ(frame->references[1], frame->id.picture_id - 80);
745 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
Chen Xingf00bf422019-06-20 10:05:55 +0200746 EXPECT_THAT(frame->PacketInfos(), SizeIs(1));
philipeldabfcae2018-09-25 12:54:37 +0200747 }));
748
749 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
750}
751
Elad Alonccb9b752019-02-19 13:01:31 +0100752TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
753 ParseGenericDescriptorTwoPackets) {
754 const int version = GetParam();
755
philipeldabfcae2018-09-25 12:54:37 +0200756 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
757 const int kPayloadType = 123;
758 const int kSpatialIndex = 1;
759
760 VideoCodec codec;
761 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200762 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200763 rtp_video_stream_receiver_->StartReceive();
764
765 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100766 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200767 RtpPacketReceived first_packet(&extension_map);
768
769 RtpGenericFrameDescriptor first_packet_descriptor;
770 first_packet_descriptor.SetFirstPacketInSubFrame(true);
771 first_packet_descriptor.SetLastPacketInSubFrame(false);
philipeldabfcae2018-09-25 12:54:37 +0200772 first_packet_descriptor.SetFrameId(100);
philipeldabfcae2018-09-25 12:54:37 +0200773 first_packet_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200774 first_packet_descriptor.SetResolution(480, 360);
Elad Alonccb9b752019-02-19 13:01:31 +0100775 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
776 first_packet_descriptor, &first_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200777
778 uint8_t* first_packet_payload = first_packet.SetPayloadSize(data.size());
779 memcpy(first_packet_payload, data.data(), data.size());
780 // The first byte is the header, so we ignore the first byte of |data|.
781 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
782 data.size() - 1);
783
784 first_packet.SetPayloadType(kPayloadType);
785 first_packet.SetSequenceNumber(1);
786 rtp_video_stream_receiver_->OnRtpPacket(first_packet);
787
788 RtpPacketReceived second_packet(&extension_map);
789 RtpGenericFrameDescriptor second_packet_descriptor;
790 second_packet_descriptor.SetFirstPacketInSubFrame(false);
791 second_packet_descriptor.SetLastPacketInSubFrame(true);
Elad Alonccb9b752019-02-19 13:01:31 +0100792 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
793 second_packet_descriptor, &second_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200794
795 second_packet.SetMarker(true);
796 second_packet.SetPayloadType(kPayloadType);
797 second_packet.SetSequenceNumber(2);
798
799 uint8_t* second_packet_payload = second_packet.SetPayloadSize(data.size());
800 memcpy(second_packet_payload, data.data(), data.size());
801 // The first byte is the header, so we ignore the first byte of |data|.
802 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
803 data.size() - 1);
804
805 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
806 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
philipelfab91292018-10-17 14:36:08 +0200807 EXPECT_EQ(frame->num_references, 0U);
philipeldabfcae2018-09-25 12:54:37 +0200808 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200809 EXPECT_EQ(frame->EncodedImage()._encodedWidth, 480u);
810 EXPECT_EQ(frame->EncodedImage()._encodedHeight, 360u);
Chen Xingf00bf422019-06-20 10:05:55 +0200811 EXPECT_THAT(frame->PacketInfos(), SizeIs(2));
philipeldabfcae2018-09-25 12:54:37 +0200812 }));
813
814 rtp_video_stream_receiver_->OnRtpPacket(second_packet);
815}
816
Elad Alonccb9b752019-02-19 13:01:31 +0100817TEST_F(RtpVideoStreamReceiverGenericDescriptorTest,
818 DropPacketsWithMultipleVersionsOfExtension) {
819 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
820 const int kPayloadType = 123;
821
822 VideoCodec codec;
823 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200824 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Elad Alonccb9b752019-02-19 13:01:31 +0100825 rtp_video_stream_receiver_->StartReceive();
826
827 RtpHeaderExtensionMap extension_map;
828 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 0);
829 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 1);
830 RtpPacketReceived rtp_packet(&extension_map);
831
832 RtpGenericFrameDescriptor generic_descriptors[2];
833 for (size_t i = 0; i < 2; ++i) {
834 generic_descriptors[i].SetFirstPacketInSubFrame(true);
835 generic_descriptors[i].SetLastPacketInSubFrame(true);
836 generic_descriptors[i].SetFrameId(100);
837 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
838 generic_descriptors[i], &rtp_packet, i));
839 }
840
841 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
842 memcpy(payload, data.data(), data.size());
843 // The first byte is the header, so we ignore the first byte of |data|.
844 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
845 data.size() - 1);
846
847 rtp_packet.SetMarker(true);
848 rtp_packet.SetPayloadType(kPayloadType);
849 rtp_packet.SetSequenceNumber(1);
850
851 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
852
853 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
854}
855
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200856TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
857 ParseGenericDescriptorRawPayload) {
858 const int version = GetParam();
859
860 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
861 const int kPayloadType = 123;
862
863 VideoCodec codec;
864 codec.plType = kPayloadType;
865 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/true);
866 rtp_video_stream_receiver_->StartReceive();
867
868 RtpHeaderExtensionMap extension_map;
869 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
870 RtpPacketReceived rtp_packet(&extension_map);
871
872 RtpGenericFrameDescriptor generic_descriptor;
873 generic_descriptor.SetFirstPacketInSubFrame(true);
874 generic_descriptor.SetLastPacketInSubFrame(true);
875 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
876 generic_descriptor, &rtp_packet, version));
877
878 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
879 memcpy(payload, data.data(), data.size());
880 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
881 data.size());
882
883 rtp_packet.SetMarker(true);
884 rtp_packet.SetPayloadType(kPayloadType);
885 rtp_packet.SetSequenceNumber(1);
886
887 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
888 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
889}
890
eladalonc0d481a2017-08-02 07:39:07 -0700891#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
892TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
893 MockRtpPacketSink secondary_sink;
894
895 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
896 EXPECT_DEATH(rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink),
897 "");
898
899 // Test tear-down.
900 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
901}
902#endif
903
johan62d02c32017-01-24 04:38:27 -0800904} // namespace webrtc