blob: b5fe0bdafa1870eaa85b02861c05fb8fb1bdca54 [file] [log] [blame]
johan62d02c32017-01-24 04:38:27 -08001/*
2 * Copyright 2017 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "video/rtp_video_stream_receiver.h"
johan62d02c32017-01-24 04:38:27 -080012
Mirko Bonadei317a1f02019-09-17 17:06:18 +020013#include <memory>
14
Johannes Krond51ec582019-04-15 13:32:41 +020015#include "api/video/video_codec_type.h"
16#include "api/video/video_frame_type.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "common_video/h264/h264_common.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "media/base/media_constants.h"
Johannes Krond51ec582019-04-15 13:32:41 +020019#include "modules/rtp_rtcp/source/rtp_format.h"
Danil Chapovalov51bf2002019-10-11 10:53:27 +020020#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
philipeldabfcae2018-09-25 12:54:37 +020021#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
22#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
Johannes Krond51ec582019-04-15 13:32:41 +020023#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Johannes Krond51ec582019-04-15 13:32:41 +020025#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "modules/utility/include/process_thread.h"
27#include "modules/video_coding/frame_object.h"
28#include "modules/video_coding/include/video_coding_defines.h"
29#include "modules/video_coding/packet.h"
30#include "modules/video_coding/rtp_frame_reference_finder.h"
Steve Anton10542f22019-01-11 09:11:00 -080031#include "rtc_base/byte_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020033#include "system_wrappers/include/clock.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020034#include "system_wrappers/include/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020035#include "test/field_trial.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020036#include "test/gmock.h"
37#include "test/gtest.h"
johan62d02c32017-01-24 04:38:27 -080038
philipeldabfcae2018-09-25 12:54:37 +020039using ::testing::_;
40using ::testing::Invoke;
Chen Xingf00bf422019-06-20 10:05:55 +020041using ::testing::SizeIs;
Elad Alonccb9b752019-02-19 13:01:31 +010042using ::testing::Values;
johan62d02c32017-01-24 04:38:27 -080043
44namespace webrtc {
45
46namespace {
47
johan62d02c32017-01-24 04:38:27 -080048const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
49
50class MockTransport : public Transport {
51 public:
52 MOCK_METHOD3(SendRtp,
53 bool(const uint8_t* packet,
54 size_t length,
55 const PacketOptions& options));
56 MOCK_METHOD2(SendRtcp, bool(const uint8_t* packet, size_t length));
57};
58
59class MockNackSender : public NackSender {
60 public:
61 MOCK_METHOD1(SendNack, void(const std::vector<uint16_t>& sequence_numbers));
Elad Alonef09c5b2019-05-31 13:25:50 +020062 MOCK_METHOD2(SendNack,
63 void(const std::vector<uint16_t>& sequence_numbers,
64 bool buffering_allowed));
johan62d02c32017-01-24 04:38:27 -080065};
66
67class MockKeyFrameRequestSender : public KeyFrameRequestSender {
68 public:
69 MOCK_METHOD0(RequestKeyFrame, void());
70};
71
72class MockOnCompleteFrameCallback
73 : public video_coding::OnCompleteFrameCallback {
74 public:
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) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200119 auto packet = std::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_ =
Niels Möller0d210ee2019-08-07 16:16:45 +0200142 ReceiveStatistics::Create(Clock::GetRealTimeClock());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200143 rtp_video_stream_receiver_ = std::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;
Johannes Krond51ec582019-04-15 13:32:41 +0200235 RTPVideoHeaderVP9 rtp_video_header_vp9;
236 rtp_video_header_vp9.InitRTPVideoHeaderVP9();
237 rtp_video_header_vp9.inter_pic_predicted =
238 (video_frame_type == VideoFrameType::kVideoFrameDelta);
Danil Chapovalov51bf2002019-10-11 10:53:27 +0200239 rtp_packetizer_ = std::make_unique<RtpPacketizerVp9>(
240 payload, pay_load_size_limits, rtp_video_header_vp9);
Johannes Krond51ec582019-04-15 13:32:41 +0200241 }
242
243 size_t NumPackets() { return rtp_packetizer_->NumPackets(); }
244 void SetColorSpace(const ColorSpace& color_space) {
245 color_space_ = color_space;
246 }
247
248 RtpPacketReceived NextPacket() {
249 RtpHeaderExtensionMap extension_map;
250 extension_map.Register<ColorSpaceExtension>(1);
251 RtpPacketToSend packet_to_send(&extension_map);
252 packet_to_send.SetSequenceNumber(sequence_number_++);
253 packet_to_send.SetSsrc(kSsrc);
254 packet_to_send.SetPayloadType(kPayloadType);
255 bool include_color_space =
256 (rtp_packetizer_->NumPackets() == 1u &&
257 video_frame_type_ == VideoFrameType::kVideoFrameKey);
258 if (include_color_space) {
259 EXPECT_TRUE(
260 packet_to_send.SetExtension<ColorSpaceExtension>(color_space_));
261 }
262 rtp_packetizer_->NextPacket(&packet_to_send);
263
264 RtpPacketReceived received_packet(&extension_map);
265 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
266 return received_packet;
267 }
268
269 private:
270 uint16_t sequence_number_ = 0;
271 VideoFrameType video_frame_type_;
272 ColorSpace color_space_;
273 std::unique_ptr<RtpPacketizer> rtp_packetizer_;
274 } received_packet_generator;
275 received_packet_generator.SetColorSpace(kColorSpace);
276
277 // Prepare the receiver for VP9.
278 VideoCodec codec;
279 codec.plType = kPayloadType;
280 codec.codecType = kVideoCodecVP9;
281 std::map<std::string, std::string> codec_params;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200282 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
283 /*raw_payload=*/false);
Johannes Krond51ec582019-04-15 13:32:41 +0200284
285 // Generate key frame packets.
286 received_packet_generator.SetPayload(kKeyFramePayload,
287 VideoFrameType::kVideoFrameKey);
288 EXPECT_EQ(received_packet_generator.NumPackets(), 2u);
289 RtpPacketReceived key_frame_packet1 = received_packet_generator.NextPacket();
290 RtpPacketReceived key_frame_packet2 = received_packet_generator.NextPacket();
291
292 // Generate delta frame packet.
293 received_packet_generator.SetPayload(kDeltaFramePayload,
294 VideoFrameType::kVideoFrameDelta);
295 EXPECT_EQ(received_packet_generator.NumPackets(), 1u);
296 RtpPacketReceived delta_frame_packet = received_packet_generator.NextPacket();
297
298 rtp_video_stream_receiver_->StartReceive();
299 mock_on_complete_frame_callback_.AppendExpectedBitstream(
300 kKeyFramePayload.data(), kKeyFramePayload.size());
301
302 // Send the key frame and expect a callback with color space information.
303 EXPECT_FALSE(key_frame_packet1.GetExtension<ColorSpaceExtension>());
304 EXPECT_TRUE(key_frame_packet2.GetExtension<ColorSpaceExtension>());
305 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
306 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
307 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
308 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
309 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
310 }));
311 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet2);
312 // Resend the first key frame packet to simulate padding for example.
313 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
314
315 mock_on_complete_frame_callback_.ClearExpectedBitstream();
316 mock_on_complete_frame_callback_.AppendExpectedBitstream(
317 kDeltaFramePayload.data(), kDeltaFramePayload.size());
318
319 // Expect delta frame to have color space set even though color space not
320 // included in the RTP packet.
321 EXPECT_FALSE(delta_frame_packet.GetExtension<ColorSpaceExtension>());
322 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
323 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
324 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
325 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
326 }));
327 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
328}
329
nisseb1f2ff92017-06-09 04:01:55 -0700330TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200331 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100332 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800333 const std::vector<uint8_t> data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200334 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100335 video_header.is_first_packet_in_frame = true;
336 video_header.is_last_packet_in_frame = true;
337 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200338 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800339 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
340 data.size());
341 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200342 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
343 video_header);
johan62d02c32017-01-24 04:38:27 -0800344}
345
philipeld8f6c162018-01-19 14:41:41 +0100346TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
347 const uint8_t kRedPayloadType = 125;
348 VideoCodec codec;
349 codec.plType = kRedPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200350 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200351 const std::vector<uint8_t> data({
352 0x80, // RTP version.
353 kRedPayloadType, // Payload type.
354 0, 0, 0, 0, 0, 0, // Don't care.
355 0, 0, 0x4, 0x57, // SSRC
356 kRedPayloadType, // RED header.
357 0, 0, 0, 0, 0 // Don't care.
358 });
philipeld8f6c162018-01-19 14:41:41 +0100359 RtpPacketReceived packet;
360 EXPECT_TRUE(packet.Parse(data.data(), data.size()));
361 rtp_video_stream_receiver_->StartReceive();
362 rtp_video_stream_receiver_->OnRtpPacket(packet);
363}
364
Danil Chapovalova715f282018-07-11 17:50:41 +0200365TEST_F(RtpVideoStreamReceiverTest,
366 DropsPacketWithRedPayloadTypeAndEmptyPayload) {
367 const uint8_t kRedPayloadType = 125;
368 config_.rtp.red_payload_type = kRedPayloadType;
369 SetUp(); // re-create rtp_video_stream_receiver with red payload type.
370 // clang-format off
371 const uint8_t data[] = {
372 0x80, // RTP version.
373 kRedPayloadType, // Payload type.
374 0, 0, 0, 0, 0, 0, // Don't care.
375 0, 0, 0x4, 0x57, // SSRC
376 // Empty rtp payload.
377 };
378 // clang-format on
379 RtpPacketReceived packet;
380 // Manually convert to CopyOnWriteBuffer to be sure capacity == size
381 // and asan bot can catch read buffer overflow.
382 EXPECT_TRUE(packet.Parse(rtc::CopyOnWriteBuffer(data)));
383 rtp_video_stream_receiver_->StartReceive();
384 rtp_video_stream_receiver_->OnRtpPacket(packet);
385 // Expect asan doesn't find anything.
386}
387
nisseb1f2ff92017-06-09 04:01:55 -0700388TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrameBitstreamError) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200389 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100390 RTPVideoHeader video_header;
johan62d02c32017-01-24 04:38:27 -0800391 const std::vector<uint8_t> data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200392 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100393 video_header.is_first_packet_in_frame = true;
394 video_header.is_last_packet_in_frame = true;
395 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200396 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800397 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
398 mock_on_complete_frame_callback_.AppendExpectedBitstream(
399 expected_bitsteam, sizeof(expected_bitsteam));
400 EXPECT_CALL(mock_on_complete_frame_callback_,
401 DoOnCompleteFrameFailBitstream(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200402 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
403 video_header);
johan62d02c32017-01-24 04:38:27 -0800404}
405
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100406class RtpVideoStreamReceiverTestH264
407 : public RtpVideoStreamReceiverTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200408 public ::testing::WithParamInterface<std::string> {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100409 protected:
410 RtpVideoStreamReceiverTestH264() : RtpVideoStreamReceiverTest(GetParam()) {}
411};
412
Elad Alonccb9b752019-02-19 13:01:31 +0100413INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
414 RtpVideoStreamReceiverTestH264,
415 Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100416
417TEST_P(RtpVideoStreamReceiverTestH264, InBandSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800418 std::vector<uint8_t> sps_data;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200419 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100420 RTPVideoHeader sps_video_header = GetDefaultH264VideoHeader();
421 AddSps(&sps_video_header, 0, &sps_data);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200422 rtp_packet.SetSequenceNumber(0);
Niels Möller125b5d62019-03-11 16:11:07 +0100423 sps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200424 sps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800425 mock_on_complete_frame_callback_.AppendExpectedBitstream(
426 kH264StartCode, sizeof(kH264StartCode));
427 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
428 sps_data.size());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200429 rtp_video_stream_receiver_->OnReceivedPayloadData(sps_data, rtp_packet,
430 sps_video_header);
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);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200435 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100436 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());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200442 rtp_video_stream_receiver_->OnReceivedPayloadData(pps_data, rtp_packet,
443 pps_video_header);
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);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200448 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100449 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(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200458 rtp_video_stream_receiver_->OnReceivedPayloadData(idr_data, rtp_packet,
459 idr_video_header);
johan62d02c32017-01-24 04:38:27 -0800460}
461
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100462TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800463 constexpr int kPayloadType = 99;
464 VideoCodec codec;
465 codec.plType = kPayloadType;
466 std::map<std::string, std::string> codec_params;
467 // Example parameter sets from https://tools.ietf.org/html/rfc3984#section-8.2
468 // .
469 codec_params.insert(
470 {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="});
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200471 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
472 /*raw_payload=*/false);
johan62d02c32017-01-24 04:38:27 -0800473 const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
474 0x53, 0x05, 0x89, 0x88};
475 mock_on_complete_frame_callback_.AppendExpectedBitstream(
476 kH264StartCode, sizeof(kH264StartCode));
477 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_sps,
478 sizeof(binary_sps));
479 const uint8_t binary_pps[] = {0x68, 0xc9, 0x63, 0x88};
480 mock_on_complete_frame_callback_.AppendExpectedBitstream(
481 kH264StartCode, sizeof(kH264StartCode));
482 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_pps,
483 sizeof(binary_pps));
484
485 std::vector<uint8_t> data;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200486 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100487 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
488 AddIdr(&video_header, 0);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200489 rtp_packet.SetPayloadType(kPayloadType);
490 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100491 video_header.is_first_packet_in_frame = true;
492 video_header.is_last_packet_in_frame = true;
493 video_header.codec = kVideoCodecH264;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200494 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800495 data.insert(data.end(), {1, 2, 3});
496 mock_on_complete_frame_callback_.AppendExpectedBitstream(
497 kH264StartCode, sizeof(kH264StartCode));
498 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
499 data.size());
500 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200501 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
502 video_header);
johan62d02c32017-01-24 04:38:27 -0800503}
504
nisseb1f2ff92017-06-09 04:01:55 -0700505TEST_F(RtpVideoStreamReceiverTest, PaddingInMediaStream) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200506 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100507 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
philipel54ca9192017-03-21 05:45:18 -0700508 std::vector<uint8_t> data;
509 data.insert(data.end(), {1, 2, 3});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200510 rtp_packet.SetPayloadType(99);
511 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100512 video_header.is_first_packet_in_frame = true;
513 video_header.is_last_packet_in_frame = true;
514 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200515 video_header.frame_type = VideoFrameType::kVideoFrameKey;
philipel54ca9192017-03-21 05:45:18 -0700516 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
517 data.size());
518
519 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200520 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
521 video_header);
philipel54ca9192017-03-21 05:45:18 -0700522
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200523 rtp_packet.SetSequenceNumber(3);
524 rtp_video_stream_receiver_->OnReceivedPayloadData({}, rtp_packet,
525 video_header);
philipel54ca9192017-03-21 05:45:18 -0700526
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200527 rtp_packet.SetSequenceNumber(4);
philipel54ca9192017-03-21 05:45:18 -0700528 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möllerabbc50e2019-04-24 09:41:16 +0200529 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200530 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
531 video_header);
philipel54ca9192017-03-21 05:45:18 -0700532
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200533 rtp_packet.SetSequenceNumber(6);
534 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
535 video_header);
philipel54ca9192017-03-21 05:45:18 -0700536
537 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200538 rtp_packet.SetSequenceNumber(5);
539 rtp_video_stream_receiver_->OnReceivedPayloadData({}, rtp_packet,
540 video_header);
philipel54ca9192017-03-21 05:45:18 -0700541}
542
nisseb1f2ff92017-06-09 04:01:55 -0700543TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeIfFirstFrameIsDelta) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200544 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100545 RTPVideoHeader video_header;
philipel2c53b132017-05-16 08:06:30 -0700546 const std::vector<uint8_t> data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200547 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100548 video_header.is_first_packet_in_frame = true;
549 video_header.is_last_packet_in_frame = true;
550 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200551 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Niels Möller2f5554d2019-05-29 13:35:14 +0200552 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200553 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
554 video_header);
philipel2c53b132017-05-16 08:06:30 -0700555}
556
Johannes Kronbd3f3052019-08-01 15:45:54 +0200557TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeWhenPacketBufferGetsFull) {
558 constexpr int kPacketBufferMaxSize = 2048;
559
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200560 RtpPacketReceived rtp_packet;
Johannes Kronbd3f3052019-08-01 15:45:54 +0200561 RTPVideoHeader video_header;
562 const std::vector<uint8_t> data({1, 2, 3, 4});
563 video_header.is_first_packet_in_frame = true;
564 // Incomplete frames so that the packet buffer is filling up.
565 video_header.is_last_packet_in_frame = false;
566 video_header.codec = kVideoCodecGeneric;
567 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
568 uint16_t start_sequence_number = 1234;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200569 rtp_packet.SetSequenceNumber(start_sequence_number);
570 while (rtp_packet.SequenceNumber() - start_sequence_number <
Johannes Kronbd3f3052019-08-01 15:45:54 +0200571 kPacketBufferMaxSize) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200572 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
573 video_header);
574 rtp_packet.SetSequenceNumber(rtp_packet.SequenceNumber() + 2);
Johannes Kronbd3f3052019-08-01 15:45:54 +0200575 }
576
577 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200578 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
579 video_header);
Johannes Kronbd3f3052019-08-01 15:45:54 +0200580}
581
eladalonc0d481a2017-08-02 07:39:07 -0700582TEST_F(RtpVideoStreamReceiverTest, SecondarySinksGetRtpNotifications) {
583 rtp_video_stream_receiver_->StartReceive();
584
585 MockRtpPacketSink secondary_sink_1;
586 MockRtpPacketSink secondary_sink_2;
587
588 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_1);
589 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_2);
590
591 auto rtp_packet = CreateRtpPacketReceived();
592 EXPECT_CALL(secondary_sink_1, OnRtpPacket(SamePacketAs(*rtp_packet)));
593 EXPECT_CALL(secondary_sink_2, OnRtpPacket(SamePacketAs(*rtp_packet)));
594
595 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
596
597 // Test tear-down.
598 rtp_video_stream_receiver_->StopReceive();
599 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_1);
600 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_2);
601}
602
603TEST_F(RtpVideoStreamReceiverTest, RemovedSecondarySinksGetNoRtpNotifications) {
604 rtp_video_stream_receiver_->StartReceive();
605
606 MockRtpPacketSink secondary_sink;
607
608 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
609 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
610
611 auto rtp_packet = CreateRtpPacketReceived();
612
613 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
614
615 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
616
617 // Test tear-down.
618 rtp_video_stream_receiver_->StopReceive();
619}
620
621TEST_F(RtpVideoStreamReceiverTest,
622 OnlyRemovedSecondarySinksExcludedFromNotifications) {
623 rtp_video_stream_receiver_->StartReceive();
624
625 MockRtpPacketSink kept_secondary_sink;
626 MockRtpPacketSink removed_secondary_sink;
627
628 rtp_video_stream_receiver_->AddSecondarySink(&kept_secondary_sink);
629 rtp_video_stream_receiver_->AddSecondarySink(&removed_secondary_sink);
630 rtp_video_stream_receiver_->RemoveSecondarySink(&removed_secondary_sink);
631
632 auto rtp_packet = CreateRtpPacketReceived();
633 EXPECT_CALL(kept_secondary_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
634
635 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
636
637 // Test tear-down.
638 rtp_video_stream_receiver_->StopReceive();
639 rtp_video_stream_receiver_->RemoveSecondarySink(&kept_secondary_sink);
640}
641
642TEST_F(RtpVideoStreamReceiverTest,
643 SecondariesOfNonStartedStreamGetNoNotifications) {
644 // Explicitly showing that the stream is not in the |started| state,
645 // regardless of whether streams start out |started| or |stopped|.
646 rtp_video_stream_receiver_->StopReceive();
647
648 MockRtpPacketSink secondary_sink;
649 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
650
651 auto rtp_packet = CreateRtpPacketReceived();
652 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
653
654 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
655
656 // Test tear-down.
657 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
658}
659
Elad Alonccb9b752019-02-19 13:01:31 +0100660class RtpVideoStreamReceiverGenericDescriptorTest
661 : public RtpVideoStreamReceiverTest,
662 public ::testing::WithParamInterface<int> {
663 public:
664 void RegisterRtpGenericFrameDescriptorExtension(
665 RtpHeaderExtensionMap* extension_map,
666 int version) {
667 constexpr int kId00 = 5;
668 constexpr int kId01 = 6;
669 switch (version) {
670 case 0:
671 extension_map->Register<RtpGenericFrameDescriptorExtension00>(kId00);
672 return;
673 case 1:
674 extension_map->Register<RtpGenericFrameDescriptorExtension01>(kId01);
675 return;
676 }
677 RTC_NOTREACHED();
678 }
679
680 bool SetExtensionRtpGenericFrameDescriptorExtension(
681 const RtpGenericFrameDescriptor& generic_descriptor,
682 RtpPacketReceived* rtp_packet,
683 int version) {
684 switch (version) {
685 case 0:
686 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension00>(
687 generic_descriptor);
688 case 1:
689 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension01>(
690 generic_descriptor);
691 }
692 RTC_NOTREACHED();
693 return false;
694 }
695};
696
Mirko Bonadei1b575412019-09-23 08:34:50 +0200697INSTANTIATE_TEST_SUITE_P(All,
Elad Alonccb9b752019-02-19 13:01:31 +0100698 RtpVideoStreamReceiverGenericDescriptorTest,
699 Values(0, 1));
700
701TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
702 ParseGenericDescriptorOnePacket) {
703 const int version = GetParam();
704
philipeldabfcae2018-09-25 12:54:37 +0200705 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
706 const int kPayloadType = 123;
707 const int kSpatialIndex = 1;
708
709 VideoCodec codec;
710 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200711 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200712 rtp_video_stream_receiver_->StartReceive();
713
714 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100715 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200716 RtpPacketReceived rtp_packet(&extension_map);
717
718 RtpGenericFrameDescriptor generic_descriptor;
719 generic_descriptor.SetFirstPacketInSubFrame(true);
720 generic_descriptor.SetLastPacketInSubFrame(true);
philipeldabfcae2018-09-25 12:54:37 +0200721 generic_descriptor.SetFrameId(100);
722 generic_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
723 generic_descriptor.AddFrameDependencyDiff(90);
724 generic_descriptor.AddFrameDependencyDiff(80);
Elad Alonccb9b752019-02-19 13:01:31 +0100725 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
726 generic_descriptor, &rtp_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200727
728 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
729 memcpy(payload, data.data(), data.size());
730 // The first byte is the header, so we ignore the first byte of |data|.
731 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
732 data.size() - 1);
733
734 rtp_packet.SetMarker(true);
735 rtp_packet.SetPayloadType(kPayloadType);
736 rtp_packet.SetSequenceNumber(1);
737
738 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
739 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
740 EXPECT_EQ(frame->num_references, 2U);
741 EXPECT_EQ(frame->references[0], frame->id.picture_id - 90);
742 EXPECT_EQ(frame->references[1], frame->id.picture_id - 80);
743 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
Chen Xingf00bf422019-06-20 10:05:55 +0200744 EXPECT_THAT(frame->PacketInfos(), SizeIs(1));
philipeldabfcae2018-09-25 12:54:37 +0200745 }));
746
747 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
748}
749
Elad Alonccb9b752019-02-19 13:01:31 +0100750TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
751 ParseGenericDescriptorTwoPackets) {
752 const int version = GetParam();
753
philipeldabfcae2018-09-25 12:54:37 +0200754 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
755 const int kPayloadType = 123;
756 const int kSpatialIndex = 1;
757
758 VideoCodec codec;
759 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200760 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200761 rtp_video_stream_receiver_->StartReceive();
762
763 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100764 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200765 RtpPacketReceived first_packet(&extension_map);
766
767 RtpGenericFrameDescriptor first_packet_descriptor;
768 first_packet_descriptor.SetFirstPacketInSubFrame(true);
769 first_packet_descriptor.SetLastPacketInSubFrame(false);
philipeldabfcae2018-09-25 12:54:37 +0200770 first_packet_descriptor.SetFrameId(100);
philipeldabfcae2018-09-25 12:54:37 +0200771 first_packet_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200772 first_packet_descriptor.SetResolution(480, 360);
Elad Alonccb9b752019-02-19 13:01:31 +0100773 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
774 first_packet_descriptor, &first_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200775
776 uint8_t* first_packet_payload = first_packet.SetPayloadSize(data.size());
777 memcpy(first_packet_payload, data.data(), data.size());
778 // The first byte is the header, so we ignore the first byte of |data|.
779 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
780 data.size() - 1);
781
782 first_packet.SetPayloadType(kPayloadType);
783 first_packet.SetSequenceNumber(1);
784 rtp_video_stream_receiver_->OnRtpPacket(first_packet);
785
786 RtpPacketReceived second_packet(&extension_map);
787 RtpGenericFrameDescriptor second_packet_descriptor;
788 second_packet_descriptor.SetFirstPacketInSubFrame(false);
789 second_packet_descriptor.SetLastPacketInSubFrame(true);
Elad Alonccb9b752019-02-19 13:01:31 +0100790 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
791 second_packet_descriptor, &second_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200792
793 second_packet.SetMarker(true);
794 second_packet.SetPayloadType(kPayloadType);
795 second_packet.SetSequenceNumber(2);
796
797 uint8_t* second_packet_payload = second_packet.SetPayloadSize(data.size());
798 memcpy(second_packet_payload, data.data(), data.size());
799 // The first byte is the header, so we ignore the first byte of |data|.
800 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
801 data.size() - 1);
802
803 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
804 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
philipelfab91292018-10-17 14:36:08 +0200805 EXPECT_EQ(frame->num_references, 0U);
philipeldabfcae2018-09-25 12:54:37 +0200806 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200807 EXPECT_EQ(frame->EncodedImage()._encodedWidth, 480u);
808 EXPECT_EQ(frame->EncodedImage()._encodedHeight, 360u);
Chen Xingf00bf422019-06-20 10:05:55 +0200809 EXPECT_THAT(frame->PacketInfos(), SizeIs(2));
philipeldabfcae2018-09-25 12:54:37 +0200810 }));
811
812 rtp_video_stream_receiver_->OnRtpPacket(second_packet);
813}
814
Elad Alonccb9b752019-02-19 13:01:31 +0100815TEST_F(RtpVideoStreamReceiverGenericDescriptorTest,
816 DropPacketsWithMultipleVersionsOfExtension) {
817 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
818 const int kPayloadType = 123;
819
820 VideoCodec codec;
821 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200822 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Elad Alonccb9b752019-02-19 13:01:31 +0100823 rtp_video_stream_receiver_->StartReceive();
824
825 RtpHeaderExtensionMap extension_map;
826 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 0);
827 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 1);
828 RtpPacketReceived rtp_packet(&extension_map);
829
830 RtpGenericFrameDescriptor generic_descriptors[2];
831 for (size_t i = 0; i < 2; ++i) {
832 generic_descriptors[i].SetFirstPacketInSubFrame(true);
833 generic_descriptors[i].SetLastPacketInSubFrame(true);
834 generic_descriptors[i].SetFrameId(100);
835 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
836 generic_descriptors[i], &rtp_packet, i));
837 }
838
839 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
840 memcpy(payload, data.data(), data.size());
841 // The first byte is the header, so we ignore the first byte of |data|.
842 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
843 data.size() - 1);
844
845 rtp_packet.SetMarker(true);
846 rtp_packet.SetPayloadType(kPayloadType);
847 rtp_packet.SetSequenceNumber(1);
848
849 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
850
851 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
852}
853
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200854TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
855 ParseGenericDescriptorRawPayload) {
856 const int version = GetParam();
857
858 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
859 const int kPayloadType = 123;
860
861 VideoCodec codec;
862 codec.plType = kPayloadType;
863 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/true);
864 rtp_video_stream_receiver_->StartReceive();
865
866 RtpHeaderExtensionMap extension_map;
867 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
868 RtpPacketReceived rtp_packet(&extension_map);
869
870 RtpGenericFrameDescriptor generic_descriptor;
871 generic_descriptor.SetFirstPacketInSubFrame(true);
872 generic_descriptor.SetLastPacketInSubFrame(true);
873 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
874 generic_descriptor, &rtp_packet, version));
875
876 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
877 memcpy(payload, data.data(), data.size());
878 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
879 data.size());
880
881 rtp_packet.SetMarker(true);
882 rtp_packet.SetPayloadType(kPayloadType);
883 rtp_packet.SetSequenceNumber(1);
884
885 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
886 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
887}
888
eladalonc0d481a2017-08-02 07:39:07 -0700889#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
890TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
891 MockRtpPacketSink secondary_sink;
892
893 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
894 EXPECT_DEATH(rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink),
895 "");
896
897 // Test tear-down.
898 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
899}
900#endif
901
johan62d02c32017-01-24 04:38:27 -0800902} // namespace webrtc