blob: cbf2efa35db30a2ea95a2ea23c3a76ed1e31fc0a [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
Karl Wiberg918f50c2018-07-05 11:40:33 +020013#include "absl/memory/memory.h"
Johannes Krond51ec582019-04-15 13:32:41 +020014#include "api/video/video_codec_type.h"
15#include "api/video/video_frame_type.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "common_video/h264/h264_common.h"
Steve Anton10542f22019-01-11 09:11:00 -080017#include "media/base/media_constants.h"
Johannes Krond51ec582019-04-15 13:32:41 +020018#include "modules/rtp_rtcp/source/rtp_format.h"
philipeldabfcae2018-09-25 12:54:37 +020019#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
20#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
Johannes Krond51ec582019-04-15 13:32:41 +020021#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Johannes Krond51ec582019-04-15 13:32:41 +020023#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/utility/include/process_thread.h"
25#include "modules/video_coding/frame_object.h"
26#include "modules/video_coding/include/video_coding_defines.h"
27#include "modules/video_coding/packet.h"
28#include "modules/video_coding/rtp_frame_reference_finder.h"
Steve Anton10542f22019-01-11 09:11:00 -080029#include "rtc_base/byte_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020031#include "system_wrappers/include/clock.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020032#include "system_wrappers/include/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020033#include "test/field_trial.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020034#include "test/gmock.h"
35#include "test/gtest.h"
johan62d02c32017-01-24 04:38:27 -080036
philipeldabfcae2018-09-25 12:54:37 +020037using ::testing::_;
38using ::testing::Invoke;
Chen Xingf00bf422019-06-20 10:05:55 +020039using ::testing::SizeIs;
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));
Elad Alonef09c5b2019-05-31 13:25:50 +020060 MOCK_METHOD2(SendNack,
61 void(const std::vector<uint16_t>& sequence_numbers,
62 bool buffering_allowed));
johan62d02c32017-01-24 04:38:27 -080063};
64
65class MockKeyFrameRequestSender : public KeyFrameRequestSender {
66 public:
67 MOCK_METHOD0(RequestKeyFrame, void());
68};
69
70class MockOnCompleteFrameCallback
71 : public video_coding::OnCompleteFrameCallback {
72 public:
73 MockOnCompleteFrameCallback() : buffer_(rtc::ByteBuffer::ORDER_NETWORK) {}
74
philipele7c891f2018-02-22 14:35:06 +010075 MOCK_METHOD1(DoOnCompleteFrame, void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080076 MOCK_METHOD1(DoOnCompleteFrameFailNullptr,
philipele7c891f2018-02-22 14:35:06 +010077 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080078 MOCK_METHOD1(DoOnCompleteFrameFailLength,
philipele7c891f2018-02-22 14:35:06 +010079 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080080 MOCK_METHOD1(DoOnCompleteFrameFailBitstream,
philipele7c891f2018-02-22 14:35:06 +010081 void(video_coding::EncodedFrame* frame));
82 void OnCompleteFrame(std::unique_ptr<video_coding::EncodedFrame> frame) {
johan62d02c32017-01-24 04:38:27 -080083 if (!frame) {
84 DoOnCompleteFrameFailNullptr(nullptr);
85 return;
86 }
87 EXPECT_EQ(buffer_.Length(), frame->size());
88 if (buffer_.Length() != frame->size()) {
89 DoOnCompleteFrameFailLength(frame.get());
90 return;
91 }
Niels Möllerf0eee002018-11-28 16:31:29 +010092 if (frame->size() != buffer_.Length() ||
Niels Möller9c843902019-01-11 10:21:35 +010093 memcmp(buffer_.Data(), frame->data(), buffer_.Length()) != 0) {
johan62d02c32017-01-24 04:38:27 -080094 DoOnCompleteFrameFailBitstream(frame.get());
95 return;
96 }
97 DoOnCompleteFrame(frame.get());
98 }
Johannes Krond51ec582019-04-15 13:32:41 +020099
100 void ClearExpectedBitstream() { buffer_.Clear(); }
101
johan62d02c32017-01-24 04:38:27 -0800102 void AppendExpectedBitstream(const uint8_t data[], size_t size_in_bytes) {
103 // TODO(Johan): Let rtc::ByteBuffer handle uint8_t* instead of char*.
104 buffer_.WriteBytes(reinterpret_cast<const char*>(data), size_in_bytes);
105 }
106 rtc::ByteBufferWriter buffer_;
107};
108
eladalonc0d481a2017-08-02 07:39:07 -0700109class MockRtpPacketSink : public RtpPacketSinkInterface {
110 public:
111 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&));
112};
113
114constexpr uint32_t kSsrc = 111;
115constexpr uint16_t kSequenceNumber = 222;
116std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(
117 uint32_t ssrc = kSsrc,
118 uint16_t sequence_number = kSequenceNumber) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200119 auto packet = absl::make_unique<RtpPacketReceived>();
eladalonc0d481a2017-08-02 07:39:07 -0700120 packet->SetSsrc(ssrc);
121 packet->SetSequenceNumber(sequence_number);
122 return packet;
123}
124
125MATCHER_P(SamePacketAs, other, "") {
126 return arg.Ssrc() == other.Ssrc() &&
127 arg.SequenceNumber() == other.SequenceNumber();
128}
129
johan62d02c32017-01-24 04:38:27 -0800130} // namespace
131
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200132class RtpVideoStreamReceiverTest : public ::testing::Test {
johan62d02c32017-01-24 04:38:27 -0800133 public:
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100134 RtpVideoStreamReceiverTest() : RtpVideoStreamReceiverTest("") {}
135 explicit RtpVideoStreamReceiverTest(std::string field_trials)
136 : override_field_trials_(field_trials),
137 config_(CreateConfig()),
johan62d02c32017-01-24 04:38:27 -0800138 process_thread_(ProcessThread::Create("TestThread")) {}
139
140 void SetUp() {
nisseca5706d2017-09-11 02:32:16 -0700141 rtp_receive_statistics_ =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200142 absl::WrapUnique(ReceiveStatistics::Create(Clock::GetRealTimeClock()));
143 rtp_video_stream_receiver_ = absl::make_unique<RtpVideoStreamReceiver>(
Niels Möller60f4e292019-05-20 11:06:33 +0200144 Clock::GetRealTimeClock(), &mock_transport_, nullptr, nullptr, &config_,
145 rtp_receive_statistics_.get(), nullptr, process_thread_.get(),
Niels Möller2f5554d2019-05-29 13:35:14 +0200146 &mock_nack_sender_, &mock_key_frame_request_sender_,
147 &mock_on_complete_frame_callback_, nullptr);
johan62d02c32017-01-24 04:38:27 -0800148 }
149
Niels Möller125b5d62019-03-11 16:11:07 +0100150 RTPVideoHeader GetDefaultH264VideoHeader() {
151 RTPVideoHeader video_header;
152 video_header.codec = kVideoCodecH264;
153 video_header.video_type_header.emplace<RTPVideoHeaderH264>();
154 return video_header;
johan62d02c32017-01-24 04:38:27 -0800155 }
156
157 // TODO(Johan): refactor h264_sps_pps_tracker_unittests.cc to avoid duplicate
158 // code.
Niels Möller125b5d62019-03-11 16:11:07 +0100159 void AddSps(RTPVideoHeader* video_header,
philipel83c97da2017-06-21 07:22:40 -0700160 uint8_t sps_id,
161 std::vector<uint8_t>* data) {
johan62d02c32017-01-24 04:38:27 -0800162 NaluInfo info;
163 info.type = H264::NaluType::kSps;
164 info.sps_id = sps_id;
165 info.pps_id = -1;
johan62d02c32017-01-24 04:38:27 -0800166 data->push_back(H264::NaluType::kSps);
167 data->push_back(sps_id);
Niels Möller125b5d62019-03-11 16:11:07 +0100168 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200169 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800170 }
171
Niels Möller125b5d62019-03-11 16:11:07 +0100172 void AddPps(RTPVideoHeader* video_header,
philipel83c97da2017-06-21 07:22:40 -0700173 uint8_t sps_id,
174 uint8_t pps_id,
johan62d02c32017-01-24 04:38:27 -0800175 std::vector<uint8_t>* data) {
176 NaluInfo info;
177 info.type = H264::NaluType::kPps;
178 info.sps_id = sps_id;
179 info.pps_id = pps_id;
johan62d02c32017-01-24 04:38:27 -0800180 data->push_back(H264::NaluType::kPps);
181 data->push_back(pps_id);
Niels Möller125b5d62019-03-11 16:11:07 +0100182 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200183 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800184 }
185
Niels Möller125b5d62019-03-11 16:11:07 +0100186 void AddIdr(RTPVideoHeader* video_header, int pps_id) {
johan62d02c32017-01-24 04:38:27 -0800187 NaluInfo info;
188 info.type = H264::NaluType::kIdr;
189 info.sps_id = -1;
190 info.pps_id = pps_id;
Niels Möller125b5d62019-03-11 16:11:07 +0100191 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200192 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800193 }
194
195 protected:
196 static VideoReceiveStream::Config CreateConfig() {
197 VideoReceiveStream::Config config(nullptr);
198 config.rtp.remote_ssrc = 1111;
199 config.rtp.local_ssrc = 2222;
200 return config;
201 }
202
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100203 const webrtc::test::ScopedFieldTrials override_field_trials_;
johan62d02c32017-01-24 04:38:27 -0800204 VideoReceiveStream::Config config_;
205 MockNackSender mock_nack_sender_;
Niels Möller2f5554d2019-05-29 13:35:14 +0200206 MockKeyFrameRequestSender mock_key_frame_request_sender_;
johan62d02c32017-01-24 04:38:27 -0800207 MockTransport mock_transport_;
208 MockOnCompleteFrameCallback mock_on_complete_frame_callback_;
johan62d02c32017-01-24 04:38:27 -0800209 std::unique_ptr<ProcessThread> process_thread_;
nisseca5706d2017-09-11 02:32:16 -0700210 std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
nisseb1f2ff92017-06-09 04:01:55 -0700211 std::unique_ptr<RtpVideoStreamReceiver> rtp_video_stream_receiver_;
johan62d02c32017-01-24 04:38:27 -0800212};
213
Johannes Krond51ec582019-04-15 13:32:41 +0200214TEST_F(RtpVideoStreamReceiverTest, CacheColorSpaceFromLastPacketOfKeyframe) {
215 // Test that color space is cached from the last packet of a key frame and
216 // that it's not reset by padding packets without color space.
217 constexpr int kPayloadType = 99;
218 const ColorSpace kColorSpace(
219 ColorSpace::PrimaryID::kFILM, ColorSpace::TransferID::kBT2020_12,
220 ColorSpace::MatrixID::kBT2020_NCL, ColorSpace::RangeID::kFull);
221 const std::vector<uint8_t> kKeyFramePayload = {0, 1, 2, 3, 4, 5,
222 6, 7, 8, 9, 10};
223 const std::vector<uint8_t> kDeltaFramePayload = {0, 1, 2, 3, 4};
224
225 // Anonymous helper class that generates received packets.
226 class {
227 public:
228 void SetPayload(const std::vector<uint8_t>& payload,
229 VideoFrameType video_frame_type) {
230 video_frame_type_ = video_frame_type;
231 RtpPacketizer::PayloadSizeLimits pay_load_size_limits;
232 // Reduce max payload length to make sure the key frame generates two
233 // packets.
234 pay_load_size_limits.max_payload_len = 8;
235 RTPVideoHeader rtp_video_header;
236 RTPVideoHeaderVP9 rtp_video_header_vp9;
237 rtp_video_header_vp9.InitRTPVideoHeaderVP9();
238 rtp_video_header_vp9.inter_pic_predicted =
239 (video_frame_type == VideoFrameType::kVideoFrameDelta);
240 rtp_video_header.video_type_header = rtp_video_header_vp9;
241 rtp_packetizer_ = RtpPacketizer::Create(
242 kVideoCodecVP9, rtc::MakeArrayView(payload.data(), payload.size()),
243 pay_load_size_limits, rtp_video_header, video_frame_type, nullptr);
244 }
245
246 size_t NumPackets() { return rtp_packetizer_->NumPackets(); }
247 void SetColorSpace(const ColorSpace& color_space) {
248 color_space_ = color_space;
249 }
250
251 RtpPacketReceived NextPacket() {
252 RtpHeaderExtensionMap extension_map;
253 extension_map.Register<ColorSpaceExtension>(1);
254 RtpPacketToSend packet_to_send(&extension_map);
255 packet_to_send.SetSequenceNumber(sequence_number_++);
256 packet_to_send.SetSsrc(kSsrc);
257 packet_to_send.SetPayloadType(kPayloadType);
258 bool include_color_space =
259 (rtp_packetizer_->NumPackets() == 1u &&
260 video_frame_type_ == VideoFrameType::kVideoFrameKey);
261 if (include_color_space) {
262 EXPECT_TRUE(
263 packet_to_send.SetExtension<ColorSpaceExtension>(color_space_));
264 }
265 rtp_packetizer_->NextPacket(&packet_to_send);
266
267 RtpPacketReceived received_packet(&extension_map);
268 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
269 return received_packet;
270 }
271
272 private:
273 uint16_t sequence_number_ = 0;
274 VideoFrameType video_frame_type_;
275 ColorSpace color_space_;
276 std::unique_ptr<RtpPacketizer> rtp_packetizer_;
277 } received_packet_generator;
278 received_packet_generator.SetColorSpace(kColorSpace);
279
280 // Prepare the receiver for VP9.
281 VideoCodec codec;
282 codec.plType = kPayloadType;
283 codec.codecType = kVideoCodecVP9;
284 std::map<std::string, std::string> codec_params;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200285 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
286 /*raw_payload=*/false);
Johannes Krond51ec582019-04-15 13:32:41 +0200287
288 // Generate key frame packets.
289 received_packet_generator.SetPayload(kKeyFramePayload,
290 VideoFrameType::kVideoFrameKey);
291 EXPECT_EQ(received_packet_generator.NumPackets(), 2u);
292 RtpPacketReceived key_frame_packet1 = received_packet_generator.NextPacket();
293 RtpPacketReceived key_frame_packet2 = received_packet_generator.NextPacket();
294
295 // Generate delta frame packet.
296 received_packet_generator.SetPayload(kDeltaFramePayload,
297 VideoFrameType::kVideoFrameDelta);
298 EXPECT_EQ(received_packet_generator.NumPackets(), 1u);
299 RtpPacketReceived delta_frame_packet = received_packet_generator.NextPacket();
300
301 rtp_video_stream_receiver_->StartReceive();
302 mock_on_complete_frame_callback_.AppendExpectedBitstream(
303 kKeyFramePayload.data(), kKeyFramePayload.size());
304
305 // Send the key frame and expect a callback with color space information.
306 EXPECT_FALSE(key_frame_packet1.GetExtension<ColorSpaceExtension>());
307 EXPECT_TRUE(key_frame_packet2.GetExtension<ColorSpaceExtension>());
308 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
309 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
310 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
311 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
312 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
313 }));
314 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet2);
315 // Resend the first key frame packet to simulate padding for example.
316 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
317
318 mock_on_complete_frame_callback_.ClearExpectedBitstream();
319 mock_on_complete_frame_callback_.AppendExpectedBitstream(
320 kDeltaFramePayload.data(), kDeltaFramePayload.size());
321
322 // Expect delta frame to have color space set even though color space not
323 // included in the RTP packet.
324 EXPECT_FALSE(delta_frame_packet.GetExtension<ColorSpaceExtension>());
325 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
326 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
327 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
328 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
329 }));
330 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
331}
332
nisseb1f2ff92017-06-09 04:01:55 -0700333TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
Niels Möller125b5d62019-03-11 16:11:07 +0100334 RTPHeader rtp_header;
335 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800336 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100337 rtp_header.sequenceNumber = 1;
338 video_header.is_first_packet_in_frame = true;
339 video_header.is_last_packet_in_frame = true;
340 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200341 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800342 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
343 data.size());
344 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100345 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200346 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800347}
348
philipeld8f6c162018-01-19 14:41:41 +0100349TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
350 const uint8_t kRedPayloadType = 125;
351 VideoCodec codec;
352 codec.plType = kRedPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200353 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200354 const std::vector<uint8_t> data({
355 0x80, // RTP version.
356 kRedPayloadType, // Payload type.
357 0, 0, 0, 0, 0, 0, // Don't care.
358 0, 0, 0x4, 0x57, // SSRC
359 kRedPayloadType, // RED header.
360 0, 0, 0, 0, 0 // Don't care.
361 });
philipeld8f6c162018-01-19 14:41:41 +0100362 RtpPacketReceived packet;
363 EXPECT_TRUE(packet.Parse(data.data(), data.size()));
364 rtp_video_stream_receiver_->StartReceive();
365 rtp_video_stream_receiver_->OnRtpPacket(packet);
366}
367
Danil Chapovalova715f282018-07-11 17:50:41 +0200368TEST_F(RtpVideoStreamReceiverTest,
369 DropsPacketWithRedPayloadTypeAndEmptyPayload) {
370 const uint8_t kRedPayloadType = 125;
371 config_.rtp.red_payload_type = kRedPayloadType;
372 SetUp(); // re-create rtp_video_stream_receiver with red payload type.
373 // clang-format off
374 const uint8_t data[] = {
375 0x80, // RTP version.
376 kRedPayloadType, // Payload type.
377 0, 0, 0, 0, 0, 0, // Don't care.
378 0, 0, 0x4, 0x57, // SSRC
379 // Empty rtp payload.
380 };
381 // clang-format on
382 RtpPacketReceived packet;
383 // Manually convert to CopyOnWriteBuffer to be sure capacity == size
384 // and asan bot can catch read buffer overflow.
385 EXPECT_TRUE(packet.Parse(rtc::CopyOnWriteBuffer(data)));
386 rtp_video_stream_receiver_->StartReceive();
387 rtp_video_stream_receiver_->OnRtpPacket(packet);
388 // Expect asan doesn't find anything.
389}
390
nisseb1f2ff92017-06-09 04:01:55 -0700391TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrameBitstreamError) {
Niels Möller125b5d62019-03-11 16:11:07 +0100392 RTPHeader rtp_header;
393 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800394 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100395 rtp_header.sequenceNumber = 1;
396 video_header.is_first_packet_in_frame = true;
397 video_header.is_last_packet_in_frame = true;
398 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200399 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800400 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
401 mock_on_complete_frame_callback_.AppendExpectedBitstream(
402 expected_bitsteam, sizeof(expected_bitsteam));
403 EXPECT_CALL(mock_on_complete_frame_callback_,
404 DoOnCompleteFrameFailBitstream(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100405 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200406 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800407}
408
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100409class RtpVideoStreamReceiverTestH264
410 : public RtpVideoStreamReceiverTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200411 public ::testing::WithParamInterface<std::string> {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100412 protected:
413 RtpVideoStreamReceiverTestH264() : RtpVideoStreamReceiverTest(GetParam()) {}
414};
415
Elad Alonccb9b752019-02-19 13:01:31 +0100416INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
417 RtpVideoStreamReceiverTestH264,
418 Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100419
420TEST_P(RtpVideoStreamReceiverTestH264, InBandSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800421 std::vector<uint8_t> sps_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100422 RTPHeader rtp_header;
423 RTPVideoHeader sps_video_header = GetDefaultH264VideoHeader();
424 AddSps(&sps_video_header, 0, &sps_data);
425 rtp_header.sequenceNumber = 0;
426 sps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200427 sps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800428 mock_on_complete_frame_callback_.AppendExpectedBitstream(
429 kH264StartCode, sizeof(kH264StartCode));
430 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
431 sps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700432 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100433 sps_data.data(), sps_data.size(), rtp_header, sps_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200434 absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800435
436 std::vector<uint8_t> pps_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100437 RTPVideoHeader pps_video_header = GetDefaultH264VideoHeader();
438 AddPps(&pps_video_header, 0, 1, &pps_data);
439 rtp_header.sequenceNumber = 1;
440 pps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200441 pps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800442 mock_on_complete_frame_callback_.AppendExpectedBitstream(
443 kH264StartCode, sizeof(kH264StartCode));
444 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
445 pps_data.size());
nisseb1f2ff92017-06-09 04:01:55 -0700446 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100447 pps_data.data(), pps_data.size(), rtp_header, pps_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200448 absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800449
450 std::vector<uint8_t> idr_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100451 RTPVideoHeader idr_video_header = GetDefaultH264VideoHeader();
452 AddIdr(&idr_video_header, 1);
453 rtp_header.sequenceNumber = 2;
454 idr_video_header.is_first_packet_in_frame = true;
455 idr_video_header.is_last_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200456 idr_video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800457 idr_data.insert(idr_data.end(), {0x65, 1, 2, 3});
458 mock_on_complete_frame_callback_.AppendExpectedBitstream(
459 kH264StartCode, sizeof(kH264StartCode));
460 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
461 idr_data.size());
462 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
nisseb1f2ff92017-06-09 04:01:55 -0700463 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möller125b5d62019-03-11 16:11:07 +0100464 idr_data.data(), idr_data.size(), rtp_header, idr_video_header,
Niels Möllerabbc50e2019-04-24 09:41:16 +0200465 absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800466}
467
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100468TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800469 constexpr int kPayloadType = 99;
470 VideoCodec codec;
471 codec.plType = kPayloadType;
472 std::map<std::string, std::string> codec_params;
473 // Example parameter sets from https://tools.ietf.org/html/rfc3984#section-8.2
474 // .
475 codec_params.insert(
476 {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="});
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200477 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
478 /*raw_payload=*/false);
johan62d02c32017-01-24 04:38:27 -0800479 const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
480 0x53, 0x05, 0x89, 0x88};
481 mock_on_complete_frame_callback_.AppendExpectedBitstream(
482 kH264StartCode, sizeof(kH264StartCode));
483 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_sps,
484 sizeof(binary_sps));
485 const uint8_t binary_pps[] = {0x68, 0xc9, 0x63, 0x88};
486 mock_on_complete_frame_callback_.AppendExpectedBitstream(
487 kH264StartCode, sizeof(kH264StartCode));
488 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_pps,
489 sizeof(binary_pps));
490
491 std::vector<uint8_t> data;
Niels Möller125b5d62019-03-11 16:11:07 +0100492 RTPHeader rtp_header;
493 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
494 AddIdr(&video_header, 0);
495 rtp_header.payloadType = kPayloadType;
496 rtp_header.sequenceNumber = 2;
497 video_header.is_first_packet_in_frame = true;
498 video_header.is_last_packet_in_frame = true;
499 video_header.codec = kVideoCodecH264;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200500 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800501 data.insert(data.end(), {1, 2, 3});
502 mock_on_complete_frame_callback_.AppendExpectedBitstream(
503 kH264StartCode, sizeof(kH264StartCode));
504 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
505 data.size());
506 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100507 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200508 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
johan62d02c32017-01-24 04:38:27 -0800509}
510
nisseb1f2ff92017-06-09 04:01:55 -0700511TEST_F(RtpVideoStreamReceiverTest, PaddingInMediaStream) {
Niels Möller125b5d62019-03-11 16:11:07 +0100512 RTPHeader rtp_header;
513 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
philipel54ca9192017-03-21 05:45:18 -0700514 std::vector<uint8_t> data;
515 data.insert(data.end(), {1, 2, 3});
Niels Möller125b5d62019-03-11 16:11:07 +0100516 rtp_header.payloadType = 99;
517 rtp_header.sequenceNumber = 2;
518 video_header.is_first_packet_in_frame = true;
519 video_header.is_last_packet_in_frame = true;
520 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200521 video_header.frame_type = VideoFrameType::kVideoFrameKey;
philipel54ca9192017-03-21 05:45:18 -0700522 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
523 data.size());
524
525 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100526 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200527 data.data(), data.size(), 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 = 3;
530 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200531 nullptr, 0, rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700532
Niels Möller125b5d62019-03-11 16:11:07 +0100533 rtp_header.sequenceNumber = 4;
philipel54ca9192017-03-21 05:45:18 -0700534 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möllerabbc50e2019-04-24 09:41:16 +0200535 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Niels Möller125b5d62019-03-11 16:11:07 +0100536 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
Niels Möller125b5d62019-03-11 16:11:07 +0100539 rtp_header.sequenceNumber = 6;
540 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200541 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700542
543 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möller125b5d62019-03-11 16:11:07 +0100544 rtp_header.sequenceNumber = 5;
545 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200546 nullptr, 0, rtp_header, video_header, absl::nullopt, false);
philipel54ca9192017-03-21 05:45:18 -0700547}
548
nisseb1f2ff92017-06-09 04:01:55 -0700549TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeIfFirstFrameIsDelta) {
Niels Möller125b5d62019-03-11 16:11:07 +0100550 RTPHeader rtp_header;
551 RTPVideoHeader video_header;
philipel2c53b132017-05-16 08:06:30 -0700552 const std::vector<uint8_t> data({1, 2, 3, 4});
Niels Möller125b5d62019-03-11 16:11:07 +0100553 rtp_header.sequenceNumber = 1;
554 video_header.is_first_packet_in_frame = true;
555 video_header.is_last_packet_in_frame = true;
556 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200557 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Niels Möller2f5554d2019-05-29 13:35:14 +0200558 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
Niels Möller125b5d62019-03-11 16:11:07 +0100559 rtp_video_stream_receiver_->OnReceivedPayloadData(
Niels Möllerabbc50e2019-04-24 09:41:16 +0200560 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
philipel2c53b132017-05-16 08:06:30 -0700561}
562
Johannes Kronbd3f3052019-08-01 15:45:54 +0200563TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeWhenPacketBufferGetsFull) {
564 constexpr int kPacketBufferMaxSize = 2048;
565
566 RTPHeader rtp_header;
567 RTPVideoHeader video_header;
568 const std::vector<uint8_t> data({1, 2, 3, 4});
569 video_header.is_first_packet_in_frame = true;
570 // Incomplete frames so that the packet buffer is filling up.
571 video_header.is_last_packet_in_frame = false;
572 video_header.codec = kVideoCodecGeneric;
573 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
574 uint16_t start_sequence_number = 1234;
575 rtp_header.sequenceNumber = start_sequence_number;
576 while (rtp_header.sequenceNumber - start_sequence_number <
577 kPacketBufferMaxSize) {
578 rtp_video_stream_receiver_->OnReceivedPayloadData(data.data(), data.size(),
579 rtp_header, video_header,
580 absl::nullopt, false);
581 rtp_header.sequenceNumber += 2;
582 }
583
584 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
585 rtp_video_stream_receiver_->OnReceivedPayloadData(
586 data.data(), data.size(), rtp_header, video_header, absl::nullopt, false);
587}
588
eladalonc0d481a2017-08-02 07:39:07 -0700589TEST_F(RtpVideoStreamReceiverTest, SecondarySinksGetRtpNotifications) {
590 rtp_video_stream_receiver_->StartReceive();
591
592 MockRtpPacketSink secondary_sink_1;
593 MockRtpPacketSink secondary_sink_2;
594
595 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_1);
596 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_2);
597
598 auto rtp_packet = CreateRtpPacketReceived();
599 EXPECT_CALL(secondary_sink_1, OnRtpPacket(SamePacketAs(*rtp_packet)));
600 EXPECT_CALL(secondary_sink_2, OnRtpPacket(SamePacketAs(*rtp_packet)));
601
602 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
603
604 // Test tear-down.
605 rtp_video_stream_receiver_->StopReceive();
606 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_1);
607 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_2);
608}
609
610TEST_F(RtpVideoStreamReceiverTest, RemovedSecondarySinksGetNoRtpNotifications) {
611 rtp_video_stream_receiver_->StartReceive();
612
613 MockRtpPacketSink secondary_sink;
614
615 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
616 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
617
618 auto rtp_packet = CreateRtpPacketReceived();
619
620 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
621
622 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
623
624 // Test tear-down.
625 rtp_video_stream_receiver_->StopReceive();
626}
627
628TEST_F(RtpVideoStreamReceiverTest,
629 OnlyRemovedSecondarySinksExcludedFromNotifications) {
630 rtp_video_stream_receiver_->StartReceive();
631
632 MockRtpPacketSink kept_secondary_sink;
633 MockRtpPacketSink removed_secondary_sink;
634
635 rtp_video_stream_receiver_->AddSecondarySink(&kept_secondary_sink);
636 rtp_video_stream_receiver_->AddSecondarySink(&removed_secondary_sink);
637 rtp_video_stream_receiver_->RemoveSecondarySink(&removed_secondary_sink);
638
639 auto rtp_packet = CreateRtpPacketReceived();
640 EXPECT_CALL(kept_secondary_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
641
642 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
643
644 // Test tear-down.
645 rtp_video_stream_receiver_->StopReceive();
646 rtp_video_stream_receiver_->RemoveSecondarySink(&kept_secondary_sink);
647}
648
649TEST_F(RtpVideoStreamReceiverTest,
650 SecondariesOfNonStartedStreamGetNoNotifications) {
651 // Explicitly showing that the stream is not in the |started| state,
652 // regardless of whether streams start out |started| or |stopped|.
653 rtp_video_stream_receiver_->StopReceive();
654
655 MockRtpPacketSink secondary_sink;
656 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
657
658 auto rtp_packet = CreateRtpPacketReceived();
659 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
660
661 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
662
663 // Test tear-down.
664 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
665}
666
Elad Alonccb9b752019-02-19 13:01:31 +0100667class RtpVideoStreamReceiverGenericDescriptorTest
668 : public RtpVideoStreamReceiverTest,
669 public ::testing::WithParamInterface<int> {
670 public:
671 void RegisterRtpGenericFrameDescriptorExtension(
672 RtpHeaderExtensionMap* extension_map,
673 int version) {
674 constexpr int kId00 = 5;
675 constexpr int kId01 = 6;
676 switch (version) {
677 case 0:
678 extension_map->Register<RtpGenericFrameDescriptorExtension00>(kId00);
679 return;
680 case 1:
681 extension_map->Register<RtpGenericFrameDescriptorExtension01>(kId01);
682 return;
683 }
684 RTC_NOTREACHED();
685 }
686
687 bool SetExtensionRtpGenericFrameDescriptorExtension(
688 const RtpGenericFrameDescriptor& generic_descriptor,
689 RtpPacketReceived* rtp_packet,
690 int version) {
691 switch (version) {
692 case 0:
693 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension00>(
694 generic_descriptor);
695 case 1:
696 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension01>(
697 generic_descriptor);
698 }
699 RTC_NOTREACHED();
700 return false;
701 }
702};
703
704INSTANTIATE_TEST_SUITE_P(,
705 RtpVideoStreamReceiverGenericDescriptorTest,
706 Values(0, 1));
707
708TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
709 ParseGenericDescriptorOnePacket) {
710 const int version = GetParam();
711
philipeldabfcae2018-09-25 12:54:37 +0200712 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
713 const int kPayloadType = 123;
714 const int kSpatialIndex = 1;
715
716 VideoCodec codec;
717 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200718 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200719 rtp_video_stream_receiver_->StartReceive();
720
721 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100722 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200723 RtpPacketReceived rtp_packet(&extension_map);
724
725 RtpGenericFrameDescriptor generic_descriptor;
726 generic_descriptor.SetFirstPacketInSubFrame(true);
727 generic_descriptor.SetLastPacketInSubFrame(true);
philipeldabfcae2018-09-25 12:54:37 +0200728 generic_descriptor.SetFrameId(100);
729 generic_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
730 generic_descriptor.AddFrameDependencyDiff(90);
731 generic_descriptor.AddFrameDependencyDiff(80);
Elad Alonccb9b752019-02-19 13:01:31 +0100732 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
733 generic_descriptor, &rtp_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200734
735 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
736 memcpy(payload, data.data(), data.size());
737 // The first byte is the header, so we ignore the first byte of |data|.
738 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
739 data.size() - 1);
740
741 rtp_packet.SetMarker(true);
742 rtp_packet.SetPayloadType(kPayloadType);
743 rtp_packet.SetSequenceNumber(1);
744
745 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
746 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
747 EXPECT_EQ(frame->num_references, 2U);
748 EXPECT_EQ(frame->references[0], frame->id.picture_id - 90);
749 EXPECT_EQ(frame->references[1], frame->id.picture_id - 80);
750 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
Chen Xingf00bf422019-06-20 10:05:55 +0200751 EXPECT_THAT(frame->PacketInfos(), SizeIs(1));
philipeldabfcae2018-09-25 12:54:37 +0200752 }));
753
754 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
755}
756
Elad Alonccb9b752019-02-19 13:01:31 +0100757TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
758 ParseGenericDescriptorTwoPackets) {
759 const int version = GetParam();
760
philipeldabfcae2018-09-25 12:54:37 +0200761 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
762 const int kPayloadType = 123;
763 const int kSpatialIndex = 1;
764
765 VideoCodec codec;
766 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200767 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200768 rtp_video_stream_receiver_->StartReceive();
769
770 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100771 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200772 RtpPacketReceived first_packet(&extension_map);
773
774 RtpGenericFrameDescriptor first_packet_descriptor;
775 first_packet_descriptor.SetFirstPacketInSubFrame(true);
776 first_packet_descriptor.SetLastPacketInSubFrame(false);
philipeldabfcae2018-09-25 12:54:37 +0200777 first_packet_descriptor.SetFrameId(100);
philipeldabfcae2018-09-25 12:54:37 +0200778 first_packet_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200779 first_packet_descriptor.SetResolution(480, 360);
Elad Alonccb9b752019-02-19 13:01:31 +0100780 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
781 first_packet_descriptor, &first_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200782
783 uint8_t* first_packet_payload = first_packet.SetPayloadSize(data.size());
784 memcpy(first_packet_payload, data.data(), data.size());
785 // The first byte is the header, so we ignore the first byte of |data|.
786 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
787 data.size() - 1);
788
789 first_packet.SetPayloadType(kPayloadType);
790 first_packet.SetSequenceNumber(1);
791 rtp_video_stream_receiver_->OnRtpPacket(first_packet);
792
793 RtpPacketReceived second_packet(&extension_map);
794 RtpGenericFrameDescriptor second_packet_descriptor;
795 second_packet_descriptor.SetFirstPacketInSubFrame(false);
796 second_packet_descriptor.SetLastPacketInSubFrame(true);
Elad Alonccb9b752019-02-19 13:01:31 +0100797 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
798 second_packet_descriptor, &second_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200799
800 second_packet.SetMarker(true);
801 second_packet.SetPayloadType(kPayloadType);
802 second_packet.SetSequenceNumber(2);
803
804 uint8_t* second_packet_payload = second_packet.SetPayloadSize(data.size());
805 memcpy(second_packet_payload, data.data(), data.size());
806 // The first byte is the header, so we ignore the first byte of |data|.
807 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
808 data.size() - 1);
809
810 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
811 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
philipelfab91292018-10-17 14:36:08 +0200812 EXPECT_EQ(frame->num_references, 0U);
philipeldabfcae2018-09-25 12:54:37 +0200813 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200814 EXPECT_EQ(frame->EncodedImage()._encodedWidth, 480u);
815 EXPECT_EQ(frame->EncodedImage()._encodedHeight, 360u);
Chen Xingf00bf422019-06-20 10:05:55 +0200816 EXPECT_THAT(frame->PacketInfos(), SizeIs(2));
philipeldabfcae2018-09-25 12:54:37 +0200817 }));
818
819 rtp_video_stream_receiver_->OnRtpPacket(second_packet);
820}
821
Elad Alonccb9b752019-02-19 13:01:31 +0100822TEST_F(RtpVideoStreamReceiverGenericDescriptorTest,
823 DropPacketsWithMultipleVersionsOfExtension) {
824 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
825 const int kPayloadType = 123;
826
827 VideoCodec codec;
828 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200829 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Elad Alonccb9b752019-02-19 13:01:31 +0100830 rtp_video_stream_receiver_->StartReceive();
831
832 RtpHeaderExtensionMap extension_map;
833 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 0);
834 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 1);
835 RtpPacketReceived rtp_packet(&extension_map);
836
837 RtpGenericFrameDescriptor generic_descriptors[2];
838 for (size_t i = 0; i < 2; ++i) {
839 generic_descriptors[i].SetFirstPacketInSubFrame(true);
840 generic_descriptors[i].SetLastPacketInSubFrame(true);
841 generic_descriptors[i].SetFrameId(100);
842 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
843 generic_descriptors[i], &rtp_packet, i));
844 }
845
846 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
847 memcpy(payload, data.data(), data.size());
848 // The first byte is the header, so we ignore the first byte of |data|.
849 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
850 data.size() - 1);
851
852 rtp_packet.SetMarker(true);
853 rtp_packet.SetPayloadType(kPayloadType);
854 rtp_packet.SetSequenceNumber(1);
855
856 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
857
858 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
859}
860
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200861TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
862 ParseGenericDescriptorRawPayload) {
863 const int version = GetParam();
864
865 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
866 const int kPayloadType = 123;
867
868 VideoCodec codec;
869 codec.plType = kPayloadType;
870 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/true);
871 rtp_video_stream_receiver_->StartReceive();
872
873 RtpHeaderExtensionMap extension_map;
874 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
875 RtpPacketReceived rtp_packet(&extension_map);
876
877 RtpGenericFrameDescriptor generic_descriptor;
878 generic_descriptor.SetFirstPacketInSubFrame(true);
879 generic_descriptor.SetLastPacketInSubFrame(true);
880 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
881 generic_descriptor, &rtp_packet, version));
882
883 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
884 memcpy(payload, data.data(), data.size());
885 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
886 data.size());
887
888 rtp_packet.SetMarker(true);
889 rtp_packet.SetPayloadType(kPayloadType);
890 rtp_packet.SetSequenceNumber(1);
891
892 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
893 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
894}
895
eladalonc0d481a2017-08-02 07:39:07 -0700896#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
897TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
898 MockRtpPacketSink secondary_sink;
899
900 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
901 EXPECT_DEATH(rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink),
902 "");
903
904 // Test tear-down.
905 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
906}
907#endif
908
johan62d02c32017-01-24 04:38:27 -0800909} // namespace webrtc