blob: 981421c1ebd253ef8833ebf4c50fd26d8ee07494 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "test/gmock.h"
Yves Gerey665174f2018-06-19 15:03:05 +020012#include "test/gtest.h"
johan62d02c32017-01-24 04:38:27 -080013
Karl Wiberg918f50c2018-07-05 11:40:33 +020014#include "absl/memory/memory.h"
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"
Niels Möller479c0552019-05-23 16:57:01 +020019#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
Johannes Krond51ec582019-04-15 13:32:41 +020020#include "modules/rtp_rtcp/source/rtp_format.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"
36#include "video/rtp_video_stream_receiver.h"
johan62d02c32017-01-24 04:38:27 -080037
philipeldabfcae2018-09-25 12:54:37 +020038using ::testing::_;
39using ::testing::Invoke;
Elad Alonccb9b752019-02-19 13:01:31 +010040using ::testing::Values;
johan62d02c32017-01-24 04:38:27 -080041
42namespace webrtc {
43
44namespace {
45
johan62d02c32017-01-24 04:38:27 -080046const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
47
48class MockTransport : public Transport {
49 public:
50 MOCK_METHOD3(SendRtp,
51 bool(const uint8_t* packet,
52 size_t length,
53 const PacketOptions& options));
54 MOCK_METHOD2(SendRtcp, bool(const uint8_t* packet, size_t length));
55};
56
57class MockNackSender : public NackSender {
58 public:
59 MOCK_METHOD1(SendNack, void(const std::vector<uint16_t>& sequence_numbers));
60};
61
62class MockKeyFrameRequestSender : public KeyFrameRequestSender {
63 public:
64 MOCK_METHOD0(RequestKeyFrame, void());
65};
66
67class MockOnCompleteFrameCallback
68 : public video_coding::OnCompleteFrameCallback {
69 public:
70 MockOnCompleteFrameCallback() : buffer_(rtc::ByteBuffer::ORDER_NETWORK) {}
71
philipele7c891f2018-02-22 14:35:06 +010072 MOCK_METHOD1(DoOnCompleteFrame, void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080073 MOCK_METHOD1(DoOnCompleteFrameFailNullptr,
philipele7c891f2018-02-22 14:35:06 +010074 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080075 MOCK_METHOD1(DoOnCompleteFrameFailLength,
philipele7c891f2018-02-22 14:35:06 +010076 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080077 MOCK_METHOD1(DoOnCompleteFrameFailBitstream,
philipele7c891f2018-02-22 14:35:06 +010078 void(video_coding::EncodedFrame* frame));
79 void OnCompleteFrame(std::unique_ptr<video_coding::EncodedFrame> frame) {
johan62d02c32017-01-24 04:38:27 -080080 if (!frame) {
81 DoOnCompleteFrameFailNullptr(nullptr);
82 return;
83 }
84 EXPECT_EQ(buffer_.Length(), frame->size());
85 if (buffer_.Length() != frame->size()) {
86 DoOnCompleteFrameFailLength(frame.get());
87 return;
88 }
Niels Möllerf0eee002018-11-28 16:31:29 +010089 if (frame->size() != buffer_.Length() ||
Niels Möller9c843902019-01-11 10:21:35 +010090 memcmp(buffer_.Data(), frame->data(), buffer_.Length()) != 0) {
johan62d02c32017-01-24 04:38:27 -080091 DoOnCompleteFrameFailBitstream(frame.get());
92 return;
93 }
94 DoOnCompleteFrame(frame.get());
95 }
Johannes Krond51ec582019-04-15 13:32:41 +020096
97 void ClearExpectedBitstream() { buffer_.Clear(); }
98
johan62d02c32017-01-24 04:38:27 -080099 void AppendExpectedBitstream(const uint8_t data[], size_t size_in_bytes) {
100 // TODO(Johan): Let rtc::ByteBuffer handle uint8_t* instead of char*.
101 buffer_.WriteBytes(reinterpret_cast<const char*>(data), size_in_bytes);
102 }
103 rtc::ByteBufferWriter buffer_;
104};
105
eladalonc0d481a2017-08-02 07:39:07 -0700106class MockRtpPacketSink : public RtpPacketSinkInterface {
107 public:
108 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&));
109};
110
111constexpr uint32_t kSsrc = 111;
112constexpr uint16_t kSequenceNumber = 222;
113std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(
114 uint32_t ssrc = kSsrc,
115 uint16_t sequence_number = kSequenceNumber) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200116 auto packet = absl::make_unique<RtpPacketReceived>();
eladalonc0d481a2017-08-02 07:39:07 -0700117 packet->SetSsrc(ssrc);
118 packet->SetSequenceNumber(sequence_number);
119 return packet;
120}
121
122MATCHER_P(SamePacketAs, other, "") {
123 return arg.Ssrc() == other.Ssrc() &&
124 arg.SequenceNumber() == other.SequenceNumber();
125}
126
johan62d02c32017-01-24 04:38:27 -0800127} // namespace
128
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200129class RtpVideoStreamReceiverTest : public ::testing::Test {
johan62d02c32017-01-24 04:38:27 -0800130 public:
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100131 RtpVideoStreamReceiverTest() : RtpVideoStreamReceiverTest("") {}
132 explicit RtpVideoStreamReceiverTest(std::string field_trials)
133 : override_field_trials_(field_trials),
134 config_(CreateConfig()),
johan62d02c32017-01-24 04:38:27 -0800135 process_thread_(ProcessThread::Create("TestThread")) {}
136
137 void SetUp() {
nisseca5706d2017-09-11 02:32:16 -0700138 rtp_receive_statistics_ =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200139 absl::WrapUnique(ReceiveStatistics::Create(Clock::GetRealTimeClock()));
140 rtp_video_stream_receiver_ = absl::make_unique<RtpVideoStreamReceiver>(
Niels Möller60f4e292019-05-20 11:06:33 +0200141 Clock::GetRealTimeClock(), &mock_transport_, nullptr, nullptr, &config_,
142 rtp_receive_statistics_.get(), nullptr, process_thread_.get(),
Niels Möller479c0552019-05-23 16:57:01 +0200143 &mock_nack_sender_, &mock_on_complete_frame_callback_, nullptr);
johan62d02c32017-01-24 04:38:27 -0800144 }
145
Niels Möller125b5d62019-03-11 16:11:07 +0100146 RTPVideoHeader GetDefaultH264VideoHeader() {
147 RTPVideoHeader video_header;
148 video_header.codec = kVideoCodecH264;
149 video_header.video_type_header.emplace<RTPVideoHeaderH264>();
150 return video_header;
johan62d02c32017-01-24 04:38:27 -0800151 }
152
153 // TODO(Johan): refactor h264_sps_pps_tracker_unittests.cc to avoid duplicate
154 // code.
Niels Möller125b5d62019-03-11 16:11:07 +0100155 void AddSps(RTPVideoHeader* video_header,
philipel83c97da2017-06-21 07:22:40 -0700156 uint8_t sps_id,
157 std::vector<uint8_t>* data) {
johan62d02c32017-01-24 04:38:27 -0800158 NaluInfo info;
159 info.type = H264::NaluType::kSps;
160 info.sps_id = sps_id;
161 info.pps_id = -1;
johan62d02c32017-01-24 04:38:27 -0800162 data->push_back(H264::NaluType::kSps);
163 data->push_back(sps_id);
Niels Möller125b5d62019-03-11 16:11:07 +0100164 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200165 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800166 }
167
Niels Möller125b5d62019-03-11 16:11:07 +0100168 void AddPps(RTPVideoHeader* video_header,
philipel83c97da2017-06-21 07:22:40 -0700169 uint8_t sps_id,
170 uint8_t pps_id,
johan62d02c32017-01-24 04:38:27 -0800171 std::vector<uint8_t>* data) {
172 NaluInfo info;
173 info.type = H264::NaluType::kPps;
174 info.sps_id = sps_id;
175 info.pps_id = pps_id;
johan62d02c32017-01-24 04:38:27 -0800176 data->push_back(H264::NaluType::kPps);
177 data->push_back(pps_id);
Niels Möller125b5d62019-03-11 16:11:07 +0100178 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200179 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800180 }
181
Niels Möller125b5d62019-03-11 16:11:07 +0100182 void AddIdr(RTPVideoHeader* video_header, int pps_id) {
johan62d02c32017-01-24 04:38:27 -0800183 NaluInfo info;
184 info.type = H264::NaluType::kIdr;
185 info.sps_id = -1;
186 info.pps_id = pps_id;
Niels Möller125b5d62019-03-11 16:11:07 +0100187 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200188 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800189 }
190
191 protected:
192 static VideoReceiveStream::Config CreateConfig() {
193 VideoReceiveStream::Config config(nullptr);
194 config.rtp.remote_ssrc = 1111;
195 config.rtp.local_ssrc = 2222;
196 return config;
197 }
198
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100199 const webrtc::test::ScopedFieldTrials override_field_trials_;
johan62d02c32017-01-24 04:38:27 -0800200 VideoReceiveStream::Config config_;
201 MockNackSender mock_nack_sender_;
johan62d02c32017-01-24 04:38:27 -0800202 MockTransport mock_transport_;
203 MockOnCompleteFrameCallback mock_on_complete_frame_callback_;
johan62d02c32017-01-24 04:38:27 -0800204 std::unique_ptr<ProcessThread> process_thread_;
nisseca5706d2017-09-11 02:32:16 -0700205 std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
nisseb1f2ff92017-06-09 04:01:55 -0700206 std::unique_ptr<RtpVideoStreamReceiver> rtp_video_stream_receiver_;
johan62d02c32017-01-24 04:38:27 -0800207};
208
Johannes Krond51ec582019-04-15 13:32:41 +0200209TEST_F(RtpVideoStreamReceiverTest, CacheColorSpaceFromLastPacketOfKeyframe) {
210 // Test that color space is cached from the last packet of a key frame and
211 // that it's not reset by padding packets without color space.
212 constexpr int kPayloadType = 99;
213 const ColorSpace kColorSpace(
214 ColorSpace::PrimaryID::kFILM, ColorSpace::TransferID::kBT2020_12,
215 ColorSpace::MatrixID::kBT2020_NCL, ColorSpace::RangeID::kFull);
216 const std::vector<uint8_t> kKeyFramePayload = {0, 1, 2, 3, 4, 5,
217 6, 7, 8, 9, 10};
218 const std::vector<uint8_t> kDeltaFramePayload = {0, 1, 2, 3, 4};
219
220 // Anonymous helper class that generates received packets.
221 class {
222 public:
223 void SetPayload(const std::vector<uint8_t>& payload,
224 VideoFrameType video_frame_type) {
225 video_frame_type_ = video_frame_type;
226 RtpPacketizer::PayloadSizeLimits pay_load_size_limits;
227 // Reduce max payload length to make sure the key frame generates two
228 // packets.
229 pay_load_size_limits.max_payload_len = 8;
230 RTPVideoHeader rtp_video_header;
231 RTPVideoHeaderVP9 rtp_video_header_vp9;
232 rtp_video_header_vp9.InitRTPVideoHeaderVP9();
233 rtp_video_header_vp9.inter_pic_predicted =
234 (video_frame_type == VideoFrameType::kVideoFrameDelta);
235 rtp_video_header.video_type_header = rtp_video_header_vp9;
236 rtp_packetizer_ = RtpPacketizer::Create(
237 kVideoCodecVP9, rtc::MakeArrayView(payload.data(), payload.size()),
238 pay_load_size_limits, rtp_video_header, video_frame_type, nullptr);
239 }
240
241 size_t NumPackets() { return rtp_packetizer_->NumPackets(); }
242 void SetColorSpace(const ColorSpace& color_space) {
243 color_space_ = color_space;
244 }
245
246 RtpPacketReceived NextPacket() {
247 RtpHeaderExtensionMap extension_map;
248 extension_map.Register<ColorSpaceExtension>(1);
249 RtpPacketToSend packet_to_send(&extension_map);
250 packet_to_send.SetSequenceNumber(sequence_number_++);
251 packet_to_send.SetSsrc(kSsrc);
252 packet_to_send.SetPayloadType(kPayloadType);
253 bool include_color_space =
254 (rtp_packetizer_->NumPackets() == 1u &&
255 video_frame_type_ == VideoFrameType::kVideoFrameKey);
256 if (include_color_space) {
257 EXPECT_TRUE(
258 packet_to_send.SetExtension<ColorSpaceExtension>(color_space_));
259 }
260 rtp_packetizer_->NextPacket(&packet_to_send);
261
262 RtpPacketReceived received_packet(&extension_map);
263 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
264 return received_packet;
265 }
266
267 private:
268 uint16_t sequence_number_ = 0;
269 VideoFrameType video_frame_type_;
270 ColorSpace color_space_;
271 std::unique_ptr<RtpPacketizer> rtp_packetizer_;
272 } received_packet_generator;
273 received_packet_generator.SetColorSpace(kColorSpace);
274
275 // Prepare the receiver for VP9.
276 VideoCodec codec;
277 codec.plType = kPayloadType;
278 codec.codecType = kVideoCodecVP9;
279 std::map<std::string, std::string> codec_params;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200280 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
281 /*raw_payload=*/false);
Johannes Krond51ec582019-04-15 13:32:41 +0200282
283 // Generate key frame packets.
284 received_packet_generator.SetPayload(kKeyFramePayload,
285 VideoFrameType::kVideoFrameKey);
286 EXPECT_EQ(received_packet_generator.NumPackets(), 2u);
287 RtpPacketReceived key_frame_packet1 = received_packet_generator.NextPacket();
288 RtpPacketReceived key_frame_packet2 = received_packet_generator.NextPacket();
289
290 // Generate delta frame packet.
291 received_packet_generator.SetPayload(kDeltaFramePayload,
292 VideoFrameType::kVideoFrameDelta);
293 EXPECT_EQ(received_packet_generator.NumPackets(), 1u);
294 RtpPacketReceived delta_frame_packet = received_packet_generator.NextPacket();
295
296 rtp_video_stream_receiver_->StartReceive();
297 mock_on_complete_frame_callback_.AppendExpectedBitstream(
298 kKeyFramePayload.data(), kKeyFramePayload.size());
299
300 // Send the key frame and expect a callback with color space information.
301 EXPECT_FALSE(key_frame_packet1.GetExtension<ColorSpaceExtension>());
302 EXPECT_TRUE(key_frame_packet2.GetExtension<ColorSpaceExtension>());
303 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
304 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
305 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
306 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
307 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
308 }));
309 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet2);
310 // Resend the first key frame packet to simulate padding for example.
311 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
312
313 mock_on_complete_frame_callback_.ClearExpectedBitstream();
314 mock_on_complete_frame_callback_.AppendExpectedBitstream(
315 kDeltaFramePayload.data(), kDeltaFramePayload.size());
316
317 // Expect delta frame to have color space set even though color space not
318 // included in the RTP packet.
319 EXPECT_FALSE(delta_frame_packet.GetExtension<ColorSpaceExtension>());
320 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
321 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
322 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
323 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
324 }));
325 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
326}
327
nisseb1f2ff92017-06-09 04:01:55 -0700328TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
Niels Möller125b5d62019-03-11 16:11:07 +0100329 RTPHeader rtp_header;
330 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800331 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100332 rtp_header.sequenceNumber = 1;
333 video_header.is_first_packet_in_frame = true;
334 video_header.is_last_packet_in_frame = true;
335 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200336 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800337 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
338 data.size());
339 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100340 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200341 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800342}
343
philipeld8f6c162018-01-19 14:41:41 +0100344TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
345 const uint8_t kRedPayloadType = 125;
346 VideoCodec codec;
347 codec.plType = kRedPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200348 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200349 const std::vector<uint8_t> data({
350 0x80, // RTP version.
351 kRedPayloadType, // Payload type.
352 0, 0, 0, 0, 0, 0, // Don't care.
353 0, 0, 0x4, 0x57, // SSRC
354 kRedPayloadType, // RED header.
355 0, 0, 0, 0, 0 // Don't care.
356 });
philipeld8f6c162018-01-19 14:41:41 +0100357 RtpPacketReceived packet;
358 EXPECT_TRUE(packet.Parse(data.data(), data.size()));
359 rtp_video_stream_receiver_->StartReceive();
360 rtp_video_stream_receiver_->OnRtpPacket(packet);
361}
362
Danil Chapovalova715f282018-07-11 17:50:41 +0200363TEST_F(RtpVideoStreamReceiverTest,
364 DropsPacketWithRedPayloadTypeAndEmptyPayload) {
365 const uint8_t kRedPayloadType = 125;
366 config_.rtp.red_payload_type = kRedPayloadType;
367 SetUp(); // re-create rtp_video_stream_receiver with red payload type.
368 // clang-format off
369 const uint8_t data[] = {
370 0x80, // RTP version.
371 kRedPayloadType, // Payload type.
372 0, 0, 0, 0, 0, 0, // Don't care.
373 0, 0, 0x4, 0x57, // SSRC
374 // Empty rtp payload.
375 };
376 // clang-format on
377 RtpPacketReceived packet;
378 // Manually convert to CopyOnWriteBuffer to be sure capacity == size
379 // and asan bot can catch read buffer overflow.
380 EXPECT_TRUE(packet.Parse(rtc::CopyOnWriteBuffer(data)));
381 rtp_video_stream_receiver_->StartReceive();
382 rtp_video_stream_receiver_->OnRtpPacket(packet);
383 // Expect asan doesn't find anything.
384}
385
nisseb1f2ff92017-06-09 04:01:55 -0700386TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrameBitstreamError) {
Niels Möller125b5d62019-03-11 16:11:07 +0100387 RTPHeader rtp_header;
388 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800389 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100390 rtp_header.sequenceNumber = 1;
391 video_header.is_first_packet_in_frame = true;
392 video_header.is_last_packet_in_frame = true;
393 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200394 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800395 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
396 mock_on_complete_frame_callback_.AppendExpectedBitstream(
397 expected_bitsteam, sizeof(expected_bitsteam));
398 EXPECT_CALL(mock_on_complete_frame_callback_,
399 DoOnCompleteFrameFailBitstream(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100400 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200401 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800402}
403
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100404class RtpVideoStreamReceiverTestH264
405 : public RtpVideoStreamReceiverTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200406 public ::testing::WithParamInterface<std::string> {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100407 protected:
408 RtpVideoStreamReceiverTestH264() : RtpVideoStreamReceiverTest(GetParam()) {}
409};
410
Elad Alonccb9b752019-02-19 13:01:31 +0100411INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
412 RtpVideoStreamReceiverTestH264,
413 Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100414
415TEST_P(RtpVideoStreamReceiverTestH264, InBandSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800416 std::vector<uint8_t> sps_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100417 RTPHeader rtp_header;
418 RTPVideoHeader sps_video_header = GetDefaultH264VideoHeader();
419 AddSps(&sps_video_header, 0, &sps_data);
420 rtp_header.sequenceNumber = 0;
421 sps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200422 sps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800423 mock_on_complete_frame_callback_.AppendExpectedBitstream(
424 kH264StartCode, sizeof(kH264StartCode));
425 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
426 sps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700427 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100428 sps_data.data(), sps_data.size(), rtp_header, sps_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200429 absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800430
431 std::vector<uint8_t> pps_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100432 RTPVideoHeader pps_video_header = GetDefaultH264VideoHeader();
433 AddPps(&pps_video_header, 0, 1, &pps_data);
434 rtp_header.sequenceNumber = 1;
435 pps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200436 pps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800437 mock_on_complete_frame_callback_.AppendExpectedBitstream(
438 kH264StartCode, sizeof(kH264StartCode));
439 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
440 pps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700441 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100442 pps_data.data(), pps_data.size(), rtp_header, pps_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200443 absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800444
445 std::vector<uint8_t> idr_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100446 RTPVideoHeader idr_video_header = GetDefaultH264VideoHeader();
447 AddIdr(&idr_video_header, 1);
448 rtp_header.sequenceNumber = 2;
449 idr_video_header.is_first_packet_in_frame = true;
450 idr_video_header.is_last_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200451 idr_video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800452 idr_data.insert(idr_data.end(), {0x65, 1, 2, 3});
453 mock_on_complete_frame_callback_.AppendExpectedBitstream(
454 kH264StartCode, sizeof(kH264StartCode));
455 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
456 idr_data.size());
457 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700458 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100459 idr_data.data(), idr_data.size(), rtp_header, idr_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200460 absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800461}
462
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100463TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800464 constexpr int kPayloadType = 99;
465 VideoCodec codec;
466 codec.plType = kPayloadType;
467 std::map<std::string, std::string> codec_params;
468 // Example parameter sets from https://tools.ietf.org/html/rfc3984#section-8.2
469 // .
470 codec_params.insert(
471 {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="});
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200472 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
473 /*raw_payload=*/false);
johan62d02c32017-01-24 04:38:27 -0800474 const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
475 0x53, 0x05, 0x89, 0x88};
476 mock_on_complete_frame_callback_.AppendExpectedBitstream(
477 kH264StartCode, sizeof(kH264StartCode));
478 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_sps,
479 sizeof(binary_sps));
480 const uint8_t binary_pps[] = {0x68, 0xc9, 0x63, 0x88};
481 mock_on_complete_frame_callback_.AppendExpectedBitstream(
482 kH264StartCode, sizeof(kH264StartCode));
483 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_pps,
484 sizeof(binary_pps));
485
486 std::vector<uint8_t> data;
Niels Möller125b5d62019-03-11 16:11:07 +0100487 RTPHeader rtp_header;
488 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
489 AddIdr(&video_header, 0);
490 rtp_header.payloadType = kPayloadType;
491 rtp_header.sequenceNumber = 2;
492 video_header.is_first_packet_in_frame = true;
493 video_header.is_last_packet_in_frame = true;
494 video_header.codec = kVideoCodecH264;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200495 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800496 data.insert(data.end(), {1, 2, 3});
497 mock_on_complete_frame_callback_.AppendExpectedBitstream(
498 kH264StartCode, sizeof(kH264StartCode));
499 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
500 data.size());
501 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100502 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200503 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800504}
505
nisseb1f2ff92017-06-09 04:01:55 -0700506TEST_F(RtpVideoStreamReceiverTest, PaddingInMediaStream) {
Niels Möller125b5d62019-03-11 16:11:07 +0100507 RTPHeader rtp_header;
508 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
philipel54ca9192017-03-21 05:45:18 -0700509 std::vector<uint8_t> data;
510 data.insert(data.end(), {1, 2, 3});
Niels Möller125b5d62019-03-11 16:11:07 +0100511 rtp_header.payloadType = 99;
512 rtp_header.sequenceNumber = 2;
513 video_header.is_first_packet_in_frame = true;
514 video_header.is_last_packet_in_frame = true;
515 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200516 video_header.frame_type = VideoFrameType::kVideoFrameKey;
philipel54ca9192017-03-21 05:45:18 -0700517 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
518 data.size());
519
520 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100521 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200522 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700523
Niels Möller125b5d62019-03-11 16:11:07 +0100524 rtp_header.sequenceNumber = 3;
525 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200526 nullptr, 0, rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700527
Niels Möller125b5d62019-03-11 16:11:07 +0100528 rtp_header.sequenceNumber = 4;
philipel54ca9192017-03-21 05:45:18 -0700529 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möllerabbc50e2019-04-24 09:41:16 +0200530 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Niels Möller125b5d62019-03-11 16:11:07 +0100531 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200532 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700533
Niels Möller125b5d62019-03-11 16:11:07 +0100534 rtp_header.sequenceNumber = 6;
535 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200536 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700537
538 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100539 rtp_header.sequenceNumber = 5;
540 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200541 nullptr, 0, rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700542}
543
nisseb1f2ff92017-06-09 04:01:55 -0700544TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeIfFirstFrameIsDelta) {
Niels Möller479c0552019-05-23 16:57:01 +0200545 // Keep raw pointer, but pass ownership to RtpVideoStreamReceiver. Object
546 // stays alive for the duration of this test.
547 auto* mock_rtp_rtcp = new ::testing::NiceMock<MockRtpRtcp>;
548
549 rtp_video_stream_receiver_ = absl::make_unique<RtpVideoStreamReceiver>(
550 Clock::GetRealTimeClock(), absl::WrapUnique(mock_rtp_rtcp), nullptr,
551 &config_, rtp_receive_statistics_.get(), nullptr, process_thread_.get(),
552 &mock_nack_sender_, &mock_on_complete_frame_callback_, nullptr);
553
Niels Möller125b5d62019-03-11 16:11:07 +0100554 RTPHeader rtp_header;
555 RTPVideoHeader video_header;
philipel2c53b132017-05-16 08:06:30 -0700556 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100557 rtp_header.sequenceNumber = 1;
558 video_header.is_first_packet_in_frame = true;
559 video_header.is_last_packet_in_frame = true;
560 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200561 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Niels Möller479c0552019-05-23 16:57:01 +0200562 EXPECT_CALL(*mock_rtp_rtcp, RequestKeyFrame());
Niels Möller125b5d62019-03-11 16:11:07 +0100563 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200564 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel2c53b132017-05-16 08:06:30 -0700565}
566
eladalonc0d481a2017-08-02 07:39:07 -0700567TEST_F(RtpVideoStreamReceiverTest, SecondarySinksGetRtpNotifications) {
568 rtp_video_stream_receiver_->StartReceive();
569
570 MockRtpPacketSink secondary_sink_1;
571 MockRtpPacketSink secondary_sink_2;
572
573 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_1);
574 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_2);
575
576 auto rtp_packet = CreateRtpPacketReceived();
577 EXPECT_CALL(secondary_sink_1, OnRtpPacket(SamePacketAs(*rtp_packet)));
578 EXPECT_CALL(secondary_sink_2, OnRtpPacket(SamePacketAs(*rtp_packet)));
579
580 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
581
582 // Test tear-down.
583 rtp_video_stream_receiver_->StopReceive();
584 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_1);
585 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_2);
586}
587
588TEST_F(RtpVideoStreamReceiverTest, RemovedSecondarySinksGetNoRtpNotifications) {
589 rtp_video_stream_receiver_->StartReceive();
590
591 MockRtpPacketSink secondary_sink;
592
593 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
594 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
595
596 auto rtp_packet = CreateRtpPacketReceived();
597
598 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
599
600 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
601
602 // Test tear-down.
603 rtp_video_stream_receiver_->StopReceive();
604}
605
606TEST_F(RtpVideoStreamReceiverTest,
607 OnlyRemovedSecondarySinksExcludedFromNotifications) {
608 rtp_video_stream_receiver_->StartReceive();
609
610 MockRtpPacketSink kept_secondary_sink;
611 MockRtpPacketSink removed_secondary_sink;
612
613 rtp_video_stream_receiver_->AddSecondarySink(&kept_secondary_sink);
614 rtp_video_stream_receiver_->AddSecondarySink(&removed_secondary_sink);
615 rtp_video_stream_receiver_->RemoveSecondarySink(&removed_secondary_sink);
616
617 auto rtp_packet = CreateRtpPacketReceived();
618 EXPECT_CALL(kept_secondary_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
619
620 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
621
622 // Test tear-down.
623 rtp_video_stream_receiver_->StopReceive();
624 rtp_video_stream_receiver_->RemoveSecondarySink(&kept_secondary_sink);
625}
626
627TEST_F(RtpVideoStreamReceiverTest,
628 SecondariesOfNonStartedStreamGetNoNotifications) {
629 // Explicitly showing that the stream is not in the |started| state,
630 // regardless of whether streams start out |started| or |stopped|.
631 rtp_video_stream_receiver_->StopReceive();
632
633 MockRtpPacketSink secondary_sink;
634 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
635
636 auto rtp_packet = CreateRtpPacketReceived();
637 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
638
639 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
640
641 // Test tear-down.
642 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
643}
644
Elad Alonccb9b752019-02-19 13:01:31 +0100645class RtpVideoStreamReceiverGenericDescriptorTest
646 : public RtpVideoStreamReceiverTest,
647 public ::testing::WithParamInterface<int> {
648 public:
649 void RegisterRtpGenericFrameDescriptorExtension(
650 RtpHeaderExtensionMap* extension_map,
651 int version) {
652 constexpr int kId00 = 5;
653 constexpr int kId01 = 6;
654 switch (version) {
655 case 0:
656 extension_map->Register<RtpGenericFrameDescriptorExtension00>(kId00);
657 return;
658 case 1:
659 extension_map->Register<RtpGenericFrameDescriptorExtension01>(kId01);
660 return;
661 }
662 RTC_NOTREACHED();
663 }
664
665 bool SetExtensionRtpGenericFrameDescriptorExtension(
666 const RtpGenericFrameDescriptor& generic_descriptor,
667 RtpPacketReceived* rtp_packet,
668 int version) {
669 switch (version) {
670 case 0:
671 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension00>(
672 generic_descriptor);
673 case 1:
674 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension01>(
675 generic_descriptor);
676 }
677 RTC_NOTREACHED();
678 return false;
679 }
680};
681
682INSTANTIATE_TEST_SUITE_P(,
683 RtpVideoStreamReceiverGenericDescriptorTest,
684 Values(0, 1));
685
686TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
687 ParseGenericDescriptorOnePacket) {
688 const int version = GetParam();
689
philipeldabfcae2018-09-25 12:54:37 +0200690 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
691 const int kPayloadType = 123;
692 const int kSpatialIndex = 1;
693
694 VideoCodec codec;
695 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200696 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200697 rtp_video_stream_receiver_->StartReceive();
698
699 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100700 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200701 RtpPacketReceived rtp_packet(&extension_map);
702
703 RtpGenericFrameDescriptor generic_descriptor;
704 generic_descriptor.SetFirstPacketInSubFrame(true);
705 generic_descriptor.SetLastPacketInSubFrame(true);
philipeldabfcae2018-09-25 12:54:37 +0200706 generic_descriptor.SetFrameId(100);
707 generic_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
708 generic_descriptor.AddFrameDependencyDiff(90);
709 generic_descriptor.AddFrameDependencyDiff(80);
Elad Alonccb9b752019-02-19 13:01:31 +0100710 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
711 generic_descriptor, &rtp_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200712
713 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
714 memcpy(payload, data.data(), data.size());
715 // The first byte is the header, so we ignore the first byte of |data|.
716 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
717 data.size() - 1);
718
719 rtp_packet.SetMarker(true);
720 rtp_packet.SetPayloadType(kPayloadType);
721 rtp_packet.SetSequenceNumber(1);
722
723 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
724 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
725 EXPECT_EQ(frame->num_references, 2U);
726 EXPECT_EQ(frame->references[0], frame->id.picture_id - 90);
727 EXPECT_EQ(frame->references[1], frame->id.picture_id - 80);
728 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
729 }));
730
731 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
732}
733
Elad Alonccb9b752019-02-19 13:01:31 +0100734TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
735 ParseGenericDescriptorTwoPackets) {
736 const int version = GetParam();
737
philipeldabfcae2018-09-25 12:54:37 +0200738 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
739 const int kPayloadType = 123;
740 const int kSpatialIndex = 1;
741
742 VideoCodec codec;
743 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200744 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200745 rtp_video_stream_receiver_->StartReceive();
746
747 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100748 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200749 RtpPacketReceived first_packet(&extension_map);
750
751 RtpGenericFrameDescriptor first_packet_descriptor;
752 first_packet_descriptor.SetFirstPacketInSubFrame(true);
753 first_packet_descriptor.SetLastPacketInSubFrame(false);
philipeldabfcae2018-09-25 12:54:37 +0200754 first_packet_descriptor.SetFrameId(100);
philipeldabfcae2018-09-25 12:54:37 +0200755 first_packet_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200756 first_packet_descriptor.SetResolution(480, 360);
Elad Alonccb9b752019-02-19 13:01:31 +0100757 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
758 first_packet_descriptor, &first_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200759
760 uint8_t* first_packet_payload = first_packet.SetPayloadSize(data.size());
761 memcpy(first_packet_payload, data.data(), data.size());
762 // The first byte is the header, so we ignore the first byte of |data|.
763 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
764 data.size() - 1);
765
766 first_packet.SetPayloadType(kPayloadType);
767 first_packet.SetSequenceNumber(1);
768 rtp_video_stream_receiver_->OnRtpPacket(first_packet);
769
770 RtpPacketReceived second_packet(&extension_map);
771 RtpGenericFrameDescriptor second_packet_descriptor;
772 second_packet_descriptor.SetFirstPacketInSubFrame(false);
773 second_packet_descriptor.SetLastPacketInSubFrame(true);
Elad Alonccb9b752019-02-19 13:01:31 +0100774 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
775 second_packet_descriptor, &second_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200776
777 second_packet.SetMarker(true);
778 second_packet.SetPayloadType(kPayloadType);
779 second_packet.SetSequenceNumber(2);
780
781 uint8_t* second_packet_payload = second_packet.SetPayloadSize(data.size());
782 memcpy(second_packet_payload, data.data(), data.size());
783 // The first byte is the header, so we ignore the first byte of |data|.
784 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
785 data.size() - 1);
786
787 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
788 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
philipelfab91292018-10-17 14:36:08 +0200789 EXPECT_EQ(frame->num_references, 0U);
philipeldabfcae2018-09-25 12:54:37 +0200790 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200791 EXPECT_EQ(frame->EncodedImage()._encodedWidth, 480u);
792 EXPECT_EQ(frame->EncodedImage()._encodedHeight, 360u);
philipeldabfcae2018-09-25 12:54:37 +0200793 }));
794
795 rtp_video_stream_receiver_->OnRtpPacket(second_packet);
796}
797
Elad Alonccb9b752019-02-19 13:01:31 +0100798TEST_F(RtpVideoStreamReceiverGenericDescriptorTest,
799 DropPacketsWithMultipleVersionsOfExtension) {
800 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
801 const int kPayloadType = 123;
802
803 VideoCodec codec;
804 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200805 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Elad Alonccb9b752019-02-19 13:01:31 +0100806 rtp_video_stream_receiver_->StartReceive();
807
808 RtpHeaderExtensionMap extension_map;
809 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 0);
810 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 1);
811 RtpPacketReceived rtp_packet(&extension_map);
812
813 RtpGenericFrameDescriptor generic_descriptors[2];
814 for (size_t i = 0; i < 2; ++i) {
815 generic_descriptors[i].SetFirstPacketInSubFrame(true);
816 generic_descriptors[i].SetLastPacketInSubFrame(true);
817 generic_descriptors[i].SetFrameId(100);
818 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
819 generic_descriptors[i], &rtp_packet, i));
820 }
821
822 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
823 memcpy(payload, data.data(), data.size());
824 // The first byte is the header, so we ignore the first byte of |data|.
825 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
826 data.size() - 1);
827
828 rtp_packet.SetMarker(true);
829 rtp_packet.SetPayloadType(kPayloadType);
830 rtp_packet.SetSequenceNumber(1);
831
832 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
833
834 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
835}
836
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200837TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
838 ParseGenericDescriptorRawPayload) {
839 const int version = GetParam();
840
841 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
842 const int kPayloadType = 123;
843
844 VideoCodec codec;
845 codec.plType = kPayloadType;
846 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/true);
847 rtp_video_stream_receiver_->StartReceive();
848
849 RtpHeaderExtensionMap extension_map;
850 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
851 RtpPacketReceived rtp_packet(&extension_map);
852
853 RtpGenericFrameDescriptor generic_descriptor;
854 generic_descriptor.SetFirstPacketInSubFrame(true);
855 generic_descriptor.SetLastPacketInSubFrame(true);
856 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
857 generic_descriptor, &rtp_packet, version));
858
859 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
860 memcpy(payload, data.data(), data.size());
861 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
862 data.size());
863
864 rtp_packet.SetMarker(true);
865 rtp_packet.SetPayloadType(kPayloadType);
866 rtp_packet.SetSequenceNumber(1);
867
868 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
869 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
870}
871
eladalonc0d481a2017-08-02 07:39:07 -0700872#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
873TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
874 MockRtpPacketSink secondary_sink;
875
876 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
877 EXPECT_DEATH(rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink),
878 "");
879
880 // Test tear-down.
881 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
882}
883#endif
884
johan62d02c32017-01-24 04:38:27 -0800885} // namespace webrtc