blob: d9c10713b9ddc9672bc62e103e777b162146cc94 [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"
Johannes Krond51ec582019-04-15 13:32:41 +020019#include "modules/rtp_rtcp/source/rtp_format.h"
philipeldabfcae2018-09-25 12:54:37 +020020#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
21#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
Johannes Krond51ec582019-04-15 13:32:41 +020022#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Johannes Krond51ec582019-04-15 13:32:41 +020024#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/utility/include/process_thread.h"
26#include "modules/video_coding/frame_object.h"
27#include "modules/video_coding/include/video_coding_defines.h"
28#include "modules/video_coding/packet.h"
29#include "modules/video_coding/rtp_frame_reference_finder.h"
Steve Anton10542f22019-01-11 09:11:00 -080030#include "rtc_base/byte_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020031#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "system_wrappers/include/clock.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020033#include "system_wrappers/include/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "test/field_trial.h"
35#include "video/rtp_video_stream_receiver.h"
johan62d02c32017-01-24 04:38:27 -080036
philipeldabfcae2018-09-25 12:54:37 +020037using ::testing::_;
38using ::testing::Invoke;
Elad Alonccb9b752019-02-19 13:01:31 +010039using ::testing::Values;
johan62d02c32017-01-24 04:38:27 -080040
41namespace webrtc {
42
43namespace {
44
johan62d02c32017-01-24 04:38:27 -080045const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
46
47class MockTransport : public Transport {
48 public:
49 MOCK_METHOD3(SendRtp,
50 bool(const uint8_t* packet,
51 size_t length,
52 const PacketOptions& options));
53 MOCK_METHOD2(SendRtcp, bool(const uint8_t* packet, size_t length));
54};
55
56class MockNackSender : public NackSender {
57 public:
58 MOCK_METHOD1(SendNack, void(const std::vector<uint16_t>& sequence_numbers));
59};
60
61class MockKeyFrameRequestSender : public KeyFrameRequestSender {
62 public:
63 MOCK_METHOD0(RequestKeyFrame, void());
64};
65
66class MockOnCompleteFrameCallback
67 : public video_coding::OnCompleteFrameCallback {
68 public:
69 MockOnCompleteFrameCallback() : buffer_(rtc::ByteBuffer::ORDER_NETWORK) {}
70
philipele7c891f2018-02-22 14:35:06 +010071 MOCK_METHOD1(DoOnCompleteFrame, void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080072 MOCK_METHOD1(DoOnCompleteFrameFailNullptr,
philipele7c891f2018-02-22 14:35:06 +010073 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080074 MOCK_METHOD1(DoOnCompleteFrameFailLength,
philipele7c891f2018-02-22 14:35:06 +010075 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080076 MOCK_METHOD1(DoOnCompleteFrameFailBitstream,
philipele7c891f2018-02-22 14:35:06 +010077 void(video_coding::EncodedFrame* frame));
78 void OnCompleteFrame(std::unique_ptr<video_coding::EncodedFrame> frame) {
johan62d02c32017-01-24 04:38:27 -080079 if (!frame) {
80 DoOnCompleteFrameFailNullptr(nullptr);
81 return;
82 }
83 EXPECT_EQ(buffer_.Length(), frame->size());
84 if (buffer_.Length() != frame->size()) {
85 DoOnCompleteFrameFailLength(frame.get());
86 return;
87 }
Niels Möllerf0eee002018-11-28 16:31:29 +010088 if (frame->size() != buffer_.Length() ||
Niels Möller9c843902019-01-11 10:21:35 +010089 memcmp(buffer_.Data(), frame->data(), buffer_.Length()) != 0) {
johan62d02c32017-01-24 04:38:27 -080090 DoOnCompleteFrameFailBitstream(frame.get());
91 return;
92 }
93 DoOnCompleteFrame(frame.get());
94 }
Johannes Krond51ec582019-04-15 13:32:41 +020095
96 void ClearExpectedBitstream() { buffer_.Clear(); }
97
johan62d02c32017-01-24 04:38:27 -080098 void AppendExpectedBitstream(const uint8_t data[], size_t size_in_bytes) {
99 // TODO(Johan): Let rtc::ByteBuffer handle uint8_t* instead of char*.
100 buffer_.WriteBytes(reinterpret_cast<const char*>(data), size_in_bytes);
101 }
102 rtc::ByteBufferWriter buffer_;
103};
104
eladalonc0d481a2017-08-02 07:39:07 -0700105class MockRtpPacketSink : public RtpPacketSinkInterface {
106 public:
107 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&));
108};
109
110constexpr uint32_t kSsrc = 111;
111constexpr uint16_t kSequenceNumber = 222;
112std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(
113 uint32_t ssrc = kSsrc,
114 uint16_t sequence_number = kSequenceNumber) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200115 auto packet = absl::make_unique<RtpPacketReceived>();
eladalonc0d481a2017-08-02 07:39:07 -0700116 packet->SetSsrc(ssrc);
117 packet->SetSequenceNumber(sequence_number);
118 return packet;
119}
120
121MATCHER_P(SamePacketAs, other, "") {
122 return arg.Ssrc() == other.Ssrc() &&
123 arg.SequenceNumber() == other.SequenceNumber();
124}
125
johan62d02c32017-01-24 04:38:27 -0800126} // namespace
127
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200128class RtpVideoStreamReceiverTest : public ::testing::Test {
johan62d02c32017-01-24 04:38:27 -0800129 public:
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100130 RtpVideoStreamReceiverTest() : RtpVideoStreamReceiverTest("") {}
131 explicit RtpVideoStreamReceiverTest(std::string field_trials)
132 : override_field_trials_(field_trials),
133 config_(CreateConfig()),
johan62d02c32017-01-24 04:38:27 -0800134 process_thread_(ProcessThread::Create("TestThread")) {}
135
136 void SetUp() {
nisseca5706d2017-09-11 02:32:16 -0700137 rtp_receive_statistics_ =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200138 absl::WrapUnique(ReceiveStatistics::Create(Clock::GetRealTimeClock()));
139 rtp_video_stream_receiver_ = absl::make_unique<RtpVideoStreamReceiver>(
Niels Möller60f4e292019-05-20 11:06:33 +0200140 Clock::GetRealTimeClock(), &mock_transport_, nullptr, nullptr, &config_,
141 rtp_receive_statistics_.get(), nullptr, process_thread_.get(),
Niels Möller2f5554d2019-05-29 13:35:14 +0200142 &mock_nack_sender_, &mock_key_frame_request_sender_,
143 &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_;
Niels Möller2f5554d2019-05-29 13:35:14 +0200202 MockKeyFrameRequestSender mock_key_frame_request_sender_;
johan62d02c32017-01-24 04:38:27 -0800203 MockTransport mock_transport_;
204 MockOnCompleteFrameCallback mock_on_complete_frame_callback_;
johan62d02c32017-01-24 04:38:27 -0800205 std::unique_ptr<ProcessThread> process_thread_;
nisseca5706d2017-09-11 02:32:16 -0700206 std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
nisseb1f2ff92017-06-09 04:01:55 -0700207 std::unique_ptr<RtpVideoStreamReceiver> rtp_video_stream_receiver_;
johan62d02c32017-01-24 04:38:27 -0800208};
209
Johannes Krond51ec582019-04-15 13:32:41 +0200210TEST_F(RtpVideoStreamReceiverTest, CacheColorSpaceFromLastPacketOfKeyframe) {
211 // Test that color space is cached from the last packet of a key frame and
212 // that it's not reset by padding packets without color space.
213 constexpr int kPayloadType = 99;
214 const ColorSpace kColorSpace(
215 ColorSpace::PrimaryID::kFILM, ColorSpace::TransferID::kBT2020_12,
216 ColorSpace::MatrixID::kBT2020_NCL, ColorSpace::RangeID::kFull);
217 const std::vector<uint8_t> kKeyFramePayload = {0, 1, 2, 3, 4, 5,
218 6, 7, 8, 9, 10};
219 const std::vector<uint8_t> kDeltaFramePayload = {0, 1, 2, 3, 4};
220
221 // Anonymous helper class that generates received packets.
222 class {
223 public:
224 void SetPayload(const std::vector<uint8_t>& payload,
225 VideoFrameType video_frame_type) {
226 video_frame_type_ = video_frame_type;
227 RtpPacketizer::PayloadSizeLimits pay_load_size_limits;
228 // Reduce max payload length to make sure the key frame generates two
229 // packets.
230 pay_load_size_limits.max_payload_len = 8;
231 RTPVideoHeader rtp_video_header;
232 RTPVideoHeaderVP9 rtp_video_header_vp9;
233 rtp_video_header_vp9.InitRTPVideoHeaderVP9();
234 rtp_video_header_vp9.inter_pic_predicted =
235 (video_frame_type == VideoFrameType::kVideoFrameDelta);
236 rtp_video_header.video_type_header = rtp_video_header_vp9;
237 rtp_packetizer_ = RtpPacketizer::Create(
238 kVideoCodecVP9, rtc::MakeArrayView(payload.data(), payload.size()),
239 pay_load_size_limits, rtp_video_header, video_frame_type, nullptr);
240 }
241
242 size_t NumPackets() { return rtp_packetizer_->NumPackets(); }
243 void SetColorSpace(const ColorSpace& color_space) {
244 color_space_ = color_space;
245 }
246
247 RtpPacketReceived NextPacket() {
248 RtpHeaderExtensionMap extension_map;
249 extension_map.Register<ColorSpaceExtension>(1);
250 RtpPacketToSend packet_to_send(&extension_map);
251 packet_to_send.SetSequenceNumber(sequence_number_++);
252 packet_to_send.SetSsrc(kSsrc);
253 packet_to_send.SetPayloadType(kPayloadType);
254 bool include_color_space =
255 (rtp_packetizer_->NumPackets() == 1u &&
256 video_frame_type_ == VideoFrameType::kVideoFrameKey);
257 if (include_color_space) {
258 EXPECT_TRUE(
259 packet_to_send.SetExtension<ColorSpaceExtension>(color_space_));
260 }
261 rtp_packetizer_->NextPacket(&packet_to_send);
262
263 RtpPacketReceived received_packet(&extension_map);
264 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
265 return received_packet;
266 }
267
268 private:
269 uint16_t sequence_number_ = 0;
270 VideoFrameType video_frame_type_;
271 ColorSpace color_space_;
272 std::unique_ptr<RtpPacketizer> rtp_packetizer_;
273 } received_packet_generator;
274 received_packet_generator.SetColorSpace(kColorSpace);
275
276 // Prepare the receiver for VP9.
277 VideoCodec codec;
278 codec.plType = kPayloadType;
279 codec.codecType = kVideoCodecVP9;
280 std::map<std::string, std::string> codec_params;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200281 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
282 /*raw_payload=*/false);
Johannes Krond51ec582019-04-15 13:32:41 +0200283
284 // Generate key frame packets.
285 received_packet_generator.SetPayload(kKeyFramePayload,
286 VideoFrameType::kVideoFrameKey);
287 EXPECT_EQ(received_packet_generator.NumPackets(), 2u);
288 RtpPacketReceived key_frame_packet1 = received_packet_generator.NextPacket();
289 RtpPacketReceived key_frame_packet2 = received_packet_generator.NextPacket();
290
291 // Generate delta frame packet.
292 received_packet_generator.SetPayload(kDeltaFramePayload,
293 VideoFrameType::kVideoFrameDelta);
294 EXPECT_EQ(received_packet_generator.NumPackets(), 1u);
295 RtpPacketReceived delta_frame_packet = received_packet_generator.NextPacket();
296
297 rtp_video_stream_receiver_->StartReceive();
298 mock_on_complete_frame_callback_.AppendExpectedBitstream(
299 kKeyFramePayload.data(), kKeyFramePayload.size());
300
301 // Send the key frame and expect a callback with color space information.
302 EXPECT_FALSE(key_frame_packet1.GetExtension<ColorSpaceExtension>());
303 EXPECT_TRUE(key_frame_packet2.GetExtension<ColorSpaceExtension>());
304 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
305 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
306 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
307 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
308 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
309 }));
310 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet2);
311 // Resend the first key frame packet to simulate padding for example.
312 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
313
314 mock_on_complete_frame_callback_.ClearExpectedBitstream();
315 mock_on_complete_frame_callback_.AppendExpectedBitstream(
316 kDeltaFramePayload.data(), kDeltaFramePayload.size());
317
318 // Expect delta frame to have color space set even though color space not
319 // included in the RTP packet.
320 EXPECT_FALSE(delta_frame_packet.GetExtension<ColorSpaceExtension>());
321 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
322 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
323 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
324 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
325 }));
326 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
327}
328
nisseb1f2ff92017-06-09 04:01:55 -0700329TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
Niels Möller125b5d62019-03-11 16:11:07 +0100330 RTPHeader rtp_header;
331 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800332 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100333 rtp_header.sequenceNumber = 1;
334 video_header.is_first_packet_in_frame = true;
335 video_header.is_last_packet_in_frame = true;
336 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200337 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800338 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
339 data.size());
340 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100341 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200342 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800343}
344
philipeld8f6c162018-01-19 14:41:41 +0100345TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
346 const uint8_t kRedPayloadType = 125;
347 VideoCodec codec;
348 codec.plType = kRedPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200349 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200350 const std::vector<uint8_t> data({
351 0x80, // RTP version.
352 kRedPayloadType, // Payload type.
353 0, 0, 0, 0, 0, 0, // Don't care.
354 0, 0, 0x4, 0x57, // SSRC
355 kRedPayloadType, // RED header.
356 0, 0, 0, 0, 0 // Don't care.
357 });
philipeld8f6c162018-01-19 14:41:41 +0100358 RtpPacketReceived packet;
359 EXPECT_TRUE(packet.Parse(data.data(), data.size()));
360 rtp_video_stream_receiver_->StartReceive();
361 rtp_video_stream_receiver_->OnRtpPacket(packet);
362}
363
Danil Chapovalova715f282018-07-11 17:50:41 +0200364TEST_F(RtpVideoStreamReceiverTest,
365 DropsPacketWithRedPayloadTypeAndEmptyPayload) {
366 const uint8_t kRedPayloadType = 125;
367 config_.rtp.red_payload_type = kRedPayloadType;
368 SetUp(); // re-create rtp_video_stream_receiver with red payload type.
369 // clang-format off
370 const uint8_t data[] = {
371 0x80, // RTP version.
372 kRedPayloadType, // Payload type.
373 0, 0, 0, 0, 0, 0, // Don't care.
374 0, 0, 0x4, 0x57, // SSRC
375 // Empty rtp payload.
376 };
377 // clang-format on
378 RtpPacketReceived packet;
379 // Manually convert to CopyOnWriteBuffer to be sure capacity == size
380 // and asan bot can catch read buffer overflow.
381 EXPECT_TRUE(packet.Parse(rtc::CopyOnWriteBuffer(data)));
382 rtp_video_stream_receiver_->StartReceive();
383 rtp_video_stream_receiver_->OnRtpPacket(packet);
384 // Expect asan doesn't find anything.
385}
386
nisseb1f2ff92017-06-09 04:01:55 -0700387TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrameBitstreamError) {
Niels Möller125b5d62019-03-11 16:11:07 +0100388 RTPHeader rtp_header;
389 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800390 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100391 rtp_header.sequenceNumber = 1;
392 video_header.is_first_packet_in_frame = true;
393 video_header.is_last_packet_in_frame = true;
394 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200395 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800396 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
397 mock_on_complete_frame_callback_.AppendExpectedBitstream(
398 expected_bitsteam, sizeof(expected_bitsteam));
399 EXPECT_CALL(mock_on_complete_frame_callback_,
400 DoOnCompleteFrameFailBitstream(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100401 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200402 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800403}
404
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100405class RtpVideoStreamReceiverTestH264
406 : public RtpVideoStreamReceiverTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200407 public ::testing::WithParamInterface<std::string> {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100408 protected:
409 RtpVideoStreamReceiverTestH264() : RtpVideoStreamReceiverTest(GetParam()) {}
410};
411
Elad Alonccb9b752019-02-19 13:01:31 +0100412INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
413 RtpVideoStreamReceiverTestH264,
414 Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100415
416TEST_P(RtpVideoStreamReceiverTestH264, InBandSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800417 std::vector<uint8_t> sps_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100418 RTPHeader rtp_header;
419 RTPVideoHeader sps_video_header = GetDefaultH264VideoHeader();
420 AddSps(&sps_video_header, 0, &sps_data);
421 rtp_header.sequenceNumber = 0;
422 sps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200423 sps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800424 mock_on_complete_frame_callback_.AppendExpectedBitstream(
425 kH264StartCode, sizeof(kH264StartCode));
426 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
427 sps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700428 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100429 sps_data.data(), sps_data.size(), rtp_header, sps_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200430 absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800431
432 std::vector<uint8_t> pps_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100433 RTPVideoHeader pps_video_header = GetDefaultH264VideoHeader();
434 AddPps(&pps_video_header, 0, 1, &pps_data);
435 rtp_header.sequenceNumber = 1;
436 pps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200437 pps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800438 mock_on_complete_frame_callback_.AppendExpectedBitstream(
439 kH264StartCode, sizeof(kH264StartCode));
440 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
441 pps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700442 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100443 pps_data.data(), pps_data.size(), rtp_header, pps_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200444 absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800445
446 std::vector<uint8_t> idr_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100447 RTPVideoHeader idr_video_header = GetDefaultH264VideoHeader();
448 AddIdr(&idr_video_header, 1);
449 rtp_header.sequenceNumber = 2;
450 idr_video_header.is_first_packet_in_frame = true;
451 idr_video_header.is_last_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200452 idr_video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800453 idr_data.insert(idr_data.end(), {0x65, 1, 2, 3});
454 mock_on_complete_frame_callback_.AppendExpectedBitstream(
455 kH264StartCode, sizeof(kH264StartCode));
456 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
457 idr_data.size());
458 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700459 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100460 idr_data.data(), idr_data.size(), rtp_header, idr_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200461 absl::nullopt, false);
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;
Niels Möller125b5d62019-03-11 16:11:07 +0100488 RTPHeader rtp_header;
489 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
490 AddIdr(&video_header, 0);
491 rtp_header.payloadType = kPayloadType;
492 rtp_header.sequenceNumber = 2;
493 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(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100503 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200504 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800505}
506
nisseb1f2ff92017-06-09 04:01:55 -0700507TEST_F(RtpVideoStreamReceiverTest, PaddingInMediaStream) {
Niels Möller125b5d62019-03-11 16:11:07 +0100508 RTPHeader rtp_header;
509 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
philipel54ca9192017-03-21 05:45:18 -0700510 std::vector<uint8_t> data;
511 data.insert(data.end(), {1, 2, 3});
Niels Möller125b5d62019-03-11 16:11:07 +0100512 rtp_header.payloadType = 99;
513 rtp_header.sequenceNumber = 2;
514 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(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100522 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200523 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700524
Niels Möller125b5d62019-03-11 16:11:07 +0100525 rtp_header.sequenceNumber = 3;
526 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200527 nullptr, 0, rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700528
Niels Möller125b5d62019-03-11 16:11:07 +0100529 rtp_header.sequenceNumber = 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;
Niels Möller125b5d62019-03-11 16:11:07 +0100532 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200533 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700534
Niels Möller125b5d62019-03-11 16:11:07 +0100535 rtp_header.sequenceNumber = 6;
536 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200537 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700538
539 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100540 rtp_header.sequenceNumber = 5;
541 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200542 nullptr, 0, rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700543}
544
nisseb1f2ff92017-06-09 04:01:55 -0700545TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeIfFirstFrameIsDelta) {
Niels Möller125b5d62019-03-11 16:11:07 +0100546 RTPHeader rtp_header;
547 RTPVideoHeader video_header;
philipel2c53b132017-05-16 08:06:30 -0700548 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100549 rtp_header.sequenceNumber = 1;
550 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());
Niels Möller125b5d62019-03-11 16:11:07 +0100555 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200556 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel2c53b132017-05-16 08:06:30 -0700557}
558
eladalonc0d481a2017-08-02 07:39:07 -0700559TEST_F(RtpVideoStreamReceiverTest, SecondarySinksGetRtpNotifications) {
560 rtp_video_stream_receiver_->StartReceive();
561
562 MockRtpPacketSink secondary_sink_1;
563 MockRtpPacketSink secondary_sink_2;
564
565 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_1);
566 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_2);
567
568 auto rtp_packet = CreateRtpPacketReceived();
569 EXPECT_CALL(secondary_sink_1, OnRtpPacket(SamePacketAs(*rtp_packet)));
570 EXPECT_CALL(secondary_sink_2, OnRtpPacket(SamePacketAs(*rtp_packet)));
571
572 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
573
574 // Test tear-down.
575 rtp_video_stream_receiver_->StopReceive();
576 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_1);
577 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_2);
578}
579
580TEST_F(RtpVideoStreamReceiverTest, RemovedSecondarySinksGetNoRtpNotifications) {
581 rtp_video_stream_receiver_->StartReceive();
582
583 MockRtpPacketSink secondary_sink;
584
585 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
586 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
587
588 auto rtp_packet = CreateRtpPacketReceived();
589
590 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
591
592 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
593
594 // Test tear-down.
595 rtp_video_stream_receiver_->StopReceive();
596}
597
598TEST_F(RtpVideoStreamReceiverTest,
599 OnlyRemovedSecondarySinksExcludedFromNotifications) {
600 rtp_video_stream_receiver_->StartReceive();
601
602 MockRtpPacketSink kept_secondary_sink;
603 MockRtpPacketSink removed_secondary_sink;
604
605 rtp_video_stream_receiver_->AddSecondarySink(&kept_secondary_sink);
606 rtp_video_stream_receiver_->AddSecondarySink(&removed_secondary_sink);
607 rtp_video_stream_receiver_->RemoveSecondarySink(&removed_secondary_sink);
608
609 auto rtp_packet = CreateRtpPacketReceived();
610 EXPECT_CALL(kept_secondary_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
611
612 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
613
614 // Test tear-down.
615 rtp_video_stream_receiver_->StopReceive();
616 rtp_video_stream_receiver_->RemoveSecondarySink(&kept_secondary_sink);
617}
618
619TEST_F(RtpVideoStreamReceiverTest,
620 SecondariesOfNonStartedStreamGetNoNotifications) {
621 // Explicitly showing that the stream is not in the |started| state,
622 // regardless of whether streams start out |started| or |stopped|.
623 rtp_video_stream_receiver_->StopReceive();
624
625 MockRtpPacketSink secondary_sink;
626 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
627
628 auto rtp_packet = CreateRtpPacketReceived();
629 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
630
631 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
632
633 // Test tear-down.
634 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
635}
636
Elad Alonccb9b752019-02-19 13:01:31 +0100637class RtpVideoStreamReceiverGenericDescriptorTest
638 : public RtpVideoStreamReceiverTest,
639 public ::testing::WithParamInterface<int> {
640 public:
641 void RegisterRtpGenericFrameDescriptorExtension(
642 RtpHeaderExtensionMap* extension_map,
643 int version) {
644 constexpr int kId00 = 5;
645 constexpr int kId01 = 6;
646 switch (version) {
647 case 0:
648 extension_map->Register<RtpGenericFrameDescriptorExtension00>(kId00);
649 return;
650 case 1:
651 extension_map->Register<RtpGenericFrameDescriptorExtension01>(kId01);
652 return;
653 }
654 RTC_NOTREACHED();
655 }
656
657 bool SetExtensionRtpGenericFrameDescriptorExtension(
658 const RtpGenericFrameDescriptor& generic_descriptor,
659 RtpPacketReceived* rtp_packet,
660 int version) {
661 switch (version) {
662 case 0:
663 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension00>(
664 generic_descriptor);
665 case 1:
666 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension01>(
667 generic_descriptor);
668 }
669 RTC_NOTREACHED();
670 return false;
671 }
672};
673
674INSTANTIATE_TEST_SUITE_P(,
675 RtpVideoStreamReceiverGenericDescriptorTest,
676 Values(0, 1));
677
678TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
679 ParseGenericDescriptorOnePacket) {
680 const int version = GetParam();
681
philipeldabfcae2018-09-25 12:54:37 +0200682 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
683 const int kPayloadType = 123;
684 const int kSpatialIndex = 1;
685
686 VideoCodec codec;
687 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200688 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200689 rtp_video_stream_receiver_->StartReceive();
690
691 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100692 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200693 RtpPacketReceived rtp_packet(&extension_map);
694
695 RtpGenericFrameDescriptor generic_descriptor;
696 generic_descriptor.SetFirstPacketInSubFrame(true);
697 generic_descriptor.SetLastPacketInSubFrame(true);
philipeldabfcae2018-09-25 12:54:37 +0200698 generic_descriptor.SetFrameId(100);
699 generic_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
700 generic_descriptor.AddFrameDependencyDiff(90);
701 generic_descriptor.AddFrameDependencyDiff(80);
Elad Alonccb9b752019-02-19 13:01:31 +0100702 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
703 generic_descriptor, &rtp_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200704
705 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
706 memcpy(payload, data.data(), data.size());
707 // The first byte is the header, so we ignore the first byte of |data|.
708 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
709 data.size() - 1);
710
711 rtp_packet.SetMarker(true);
712 rtp_packet.SetPayloadType(kPayloadType);
713 rtp_packet.SetSequenceNumber(1);
714
715 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
716 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
717 EXPECT_EQ(frame->num_references, 2U);
718 EXPECT_EQ(frame->references[0], frame->id.picture_id - 90);
719 EXPECT_EQ(frame->references[1], frame->id.picture_id - 80);
720 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
721 }));
722
723 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
724}
725
Elad Alonccb9b752019-02-19 13:01:31 +0100726TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
727 ParseGenericDescriptorTwoPackets) {
728 const int version = GetParam();
729
philipeldabfcae2018-09-25 12:54:37 +0200730 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
731 const int kPayloadType = 123;
732 const int kSpatialIndex = 1;
733
734 VideoCodec codec;
735 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200736 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200737 rtp_video_stream_receiver_->StartReceive();
738
739 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100740 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200741 RtpPacketReceived first_packet(&extension_map);
742
743 RtpGenericFrameDescriptor first_packet_descriptor;
744 first_packet_descriptor.SetFirstPacketInSubFrame(true);
745 first_packet_descriptor.SetLastPacketInSubFrame(false);
philipeldabfcae2018-09-25 12:54:37 +0200746 first_packet_descriptor.SetFrameId(100);
philipeldabfcae2018-09-25 12:54:37 +0200747 first_packet_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200748 first_packet_descriptor.SetResolution(480, 360);
Elad Alonccb9b752019-02-19 13:01:31 +0100749 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
750 first_packet_descriptor, &first_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200751
752 uint8_t* first_packet_payload = first_packet.SetPayloadSize(data.size());
753 memcpy(first_packet_payload, data.data(), data.size());
754 // The first byte is the header, so we ignore the first byte of |data|.
755 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
756 data.size() - 1);
757
758 first_packet.SetPayloadType(kPayloadType);
759 first_packet.SetSequenceNumber(1);
760 rtp_video_stream_receiver_->OnRtpPacket(first_packet);
761
762 RtpPacketReceived second_packet(&extension_map);
763 RtpGenericFrameDescriptor second_packet_descriptor;
764 second_packet_descriptor.SetFirstPacketInSubFrame(false);
765 second_packet_descriptor.SetLastPacketInSubFrame(true);
Elad Alonccb9b752019-02-19 13:01:31 +0100766 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
767 second_packet_descriptor, &second_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200768
769 second_packet.SetMarker(true);
770 second_packet.SetPayloadType(kPayloadType);
771 second_packet.SetSequenceNumber(2);
772
773 uint8_t* second_packet_payload = second_packet.SetPayloadSize(data.size());
774 memcpy(second_packet_payload, data.data(), data.size());
775 // The first byte is the header, so we ignore the first byte of |data|.
776 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
777 data.size() - 1);
778
779 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
780 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
philipelfab91292018-10-17 14:36:08 +0200781 EXPECT_EQ(frame->num_references, 0U);
philipeldabfcae2018-09-25 12:54:37 +0200782 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200783 EXPECT_EQ(frame->EncodedImage()._encodedWidth, 480u);
784 EXPECT_EQ(frame->EncodedImage()._encodedHeight, 360u);
philipeldabfcae2018-09-25 12:54:37 +0200785 }));
786
787 rtp_video_stream_receiver_->OnRtpPacket(second_packet);
788}
789
Elad Alonccb9b752019-02-19 13:01:31 +0100790TEST_F(RtpVideoStreamReceiverGenericDescriptorTest,
791 DropPacketsWithMultipleVersionsOfExtension) {
792 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
793 const int kPayloadType = 123;
794
795 VideoCodec codec;
796 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200797 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Elad Alonccb9b752019-02-19 13:01:31 +0100798 rtp_video_stream_receiver_->StartReceive();
799
800 RtpHeaderExtensionMap extension_map;
801 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 0);
802 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 1);
803 RtpPacketReceived rtp_packet(&extension_map);
804
805 RtpGenericFrameDescriptor generic_descriptors[2];
806 for (size_t i = 0; i < 2; ++i) {
807 generic_descriptors[i].SetFirstPacketInSubFrame(true);
808 generic_descriptors[i].SetLastPacketInSubFrame(true);
809 generic_descriptors[i].SetFrameId(100);
810 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
811 generic_descriptors[i], &rtp_packet, i));
812 }
813
814 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
815 memcpy(payload, data.data(), data.size());
816 // The first byte is the header, so we ignore the first byte of |data|.
817 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
818 data.size() - 1);
819
820 rtp_packet.SetMarker(true);
821 rtp_packet.SetPayloadType(kPayloadType);
822 rtp_packet.SetSequenceNumber(1);
823
824 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
825
826 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
827}
828
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200829TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
830 ParseGenericDescriptorRawPayload) {
831 const int version = GetParam();
832
833 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
834 const int kPayloadType = 123;
835
836 VideoCodec codec;
837 codec.plType = kPayloadType;
838 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/true);
839 rtp_video_stream_receiver_->StartReceive();
840
841 RtpHeaderExtensionMap extension_map;
842 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
843 RtpPacketReceived rtp_packet(&extension_map);
844
845 RtpGenericFrameDescriptor generic_descriptor;
846 generic_descriptor.SetFirstPacketInSubFrame(true);
847 generic_descriptor.SetLastPacketInSubFrame(true);
848 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
849 generic_descriptor, &rtp_packet, version));
850
851 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
852 memcpy(payload, data.data(), data.size());
853 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
854 data.size());
855
856 rtp_packet.SetMarker(true);
857 rtp_packet.SetPayloadType(kPayloadType);
858 rtp_packet.SetSequenceNumber(1);
859
860 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
861 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
862}
863
eladalonc0d481a2017-08-02 07:39:07 -0700864#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
865TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
866 MockRtpPacketSink secondary_sink;
867
868 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
869 EXPECT_DEATH(rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink),
870 "");
871
872 // Test tear-down.
873 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
874}
875#endif
876
johan62d02c32017-01-24 04:38:27 -0800877} // namespace webrtc