blob: 569c5150f833d2fdf307a2a088771e621321fe39 [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>
Danil Chapovalovcebdbf62019-12-13 16:08:18 +010014#include <utility>
Mirko Bonadei317a1f02019-09-17 17:06:18 +020015
Johannes Krond51ec582019-04-15 13:32:41 +020016#include "api/video/video_codec_type.h"
17#include "api/video/video_frame_type.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "common_video/h264/h264_common.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "media/base/media_constants.h"
Johannes Krond51ec582019-04-15 13:32:41 +020020#include "modules/rtp_rtcp/source/rtp_format.h"
Danil Chapovalov51bf2002019-10-11 10:53:27 +020021#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
philipeldabfcae2018-09-25 12:54:37 +020022#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
23#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
Johannes Krond51ec582019-04-15 13:32:41 +020024#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Johannes Krond51ec582019-04-15 13:32:41 +020026#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "modules/utility/include/process_thread.h"
28#include "modules/video_coding/frame_object.h"
29#include "modules/video_coding/include/video_coding_defines.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#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::_;
Ruslan Burakovd08bb1e2019-11-27 16:49:10 +010040using ::testing::ElementsAre;
philipeldabfcae2018-09-25 12:54:37 +020041using ::testing::Invoke;
Chen Xingf00bf422019-06-20 10:05:55 +020042using ::testing::SizeIs;
Elad Alonccb9b752019-02-19 13:01:31 +010043using ::testing::Values;
johan62d02c32017-01-24 04:38:27 -080044
45namespace webrtc {
46
47namespace {
48
johan62d02c32017-01-24 04:38:27 -080049const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
50
Ruslan Burakovd08bb1e2019-11-27 16:49:10 +010051std::vector<uint64_t> GetAbsoluteCaptureTimestamps(
52 const video_coding::EncodedFrame* frame) {
53 std::vector<uint64_t> result;
54 for (const auto& packet_info : frame->PacketInfos()) {
55 if (packet_info.absolute_capture_time()) {
56 result.push_back(
57 packet_info.absolute_capture_time()->absolute_capture_timestamp);
58 }
59 }
60 return result;
61}
62
johan62d02c32017-01-24 04:38:27 -080063class MockTransport : public Transport {
64 public:
65 MOCK_METHOD3(SendRtp,
66 bool(const uint8_t* packet,
67 size_t length,
68 const PacketOptions& options));
69 MOCK_METHOD2(SendRtcp, bool(const uint8_t* packet, size_t length));
70};
71
72class MockNackSender : public NackSender {
73 public:
74 MOCK_METHOD1(SendNack, void(const std::vector<uint16_t>& sequence_numbers));
Elad Alonef09c5b2019-05-31 13:25:50 +020075 MOCK_METHOD2(SendNack,
76 void(const std::vector<uint16_t>& sequence_numbers,
77 bool buffering_allowed));
johan62d02c32017-01-24 04:38:27 -080078};
79
80class MockKeyFrameRequestSender : public KeyFrameRequestSender {
81 public:
82 MOCK_METHOD0(RequestKeyFrame, void());
83};
84
85class MockOnCompleteFrameCallback
86 : public video_coding::OnCompleteFrameCallback {
87 public:
philipele7c891f2018-02-22 14:35:06 +010088 MOCK_METHOD1(DoOnCompleteFrame, void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080089 MOCK_METHOD1(DoOnCompleteFrameFailNullptr,
philipele7c891f2018-02-22 14:35:06 +010090 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080091 MOCK_METHOD1(DoOnCompleteFrameFailLength,
philipele7c891f2018-02-22 14:35:06 +010092 void(video_coding::EncodedFrame* frame));
johan62d02c32017-01-24 04:38:27 -080093 MOCK_METHOD1(DoOnCompleteFrameFailBitstream,
philipele7c891f2018-02-22 14:35:06 +010094 void(video_coding::EncodedFrame* frame));
95 void OnCompleteFrame(std::unique_ptr<video_coding::EncodedFrame> frame) {
johan62d02c32017-01-24 04:38:27 -080096 if (!frame) {
97 DoOnCompleteFrameFailNullptr(nullptr);
98 return;
99 }
100 EXPECT_EQ(buffer_.Length(), frame->size());
101 if (buffer_.Length() != frame->size()) {
102 DoOnCompleteFrameFailLength(frame.get());
103 return;
104 }
Niels Möllerf0eee002018-11-28 16:31:29 +0100105 if (frame->size() != buffer_.Length() ||
Niels Möller9c843902019-01-11 10:21:35 +0100106 memcmp(buffer_.Data(), frame->data(), buffer_.Length()) != 0) {
johan62d02c32017-01-24 04:38:27 -0800107 DoOnCompleteFrameFailBitstream(frame.get());
108 return;
109 }
110 DoOnCompleteFrame(frame.get());
111 }
Johannes Krond51ec582019-04-15 13:32:41 +0200112
113 void ClearExpectedBitstream() { buffer_.Clear(); }
114
johan62d02c32017-01-24 04:38:27 -0800115 void AppendExpectedBitstream(const uint8_t data[], size_t size_in_bytes) {
116 // TODO(Johan): Let rtc::ByteBuffer handle uint8_t* instead of char*.
117 buffer_.WriteBytes(reinterpret_cast<const char*>(data), size_in_bytes);
118 }
119 rtc::ByteBufferWriter buffer_;
120};
121
eladalonc0d481a2017-08-02 07:39:07 -0700122class MockRtpPacketSink : public RtpPacketSinkInterface {
123 public:
124 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&));
125};
126
127constexpr uint32_t kSsrc = 111;
128constexpr uint16_t kSequenceNumber = 222;
129std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived(
130 uint32_t ssrc = kSsrc,
131 uint16_t sequence_number = kSequenceNumber) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200132 auto packet = std::make_unique<RtpPacketReceived>();
eladalonc0d481a2017-08-02 07:39:07 -0700133 packet->SetSsrc(ssrc);
134 packet->SetSequenceNumber(sequence_number);
135 return packet;
136}
137
138MATCHER_P(SamePacketAs, other, "") {
139 return arg.Ssrc() == other.Ssrc() &&
140 arg.SequenceNumber() == other.SequenceNumber();
141}
142
johan62d02c32017-01-24 04:38:27 -0800143} // namespace
144
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200145class RtpVideoStreamReceiverTest : public ::testing::Test {
johan62d02c32017-01-24 04:38:27 -0800146 public:
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100147 RtpVideoStreamReceiverTest() : RtpVideoStreamReceiverTest("") {}
148 explicit RtpVideoStreamReceiverTest(std::string field_trials)
149 : override_field_trials_(field_trials),
150 config_(CreateConfig()),
johan62d02c32017-01-24 04:38:27 -0800151 process_thread_(ProcessThread::Create("TestThread")) {}
152
153 void SetUp() {
nisseca5706d2017-09-11 02:32:16 -0700154 rtp_receive_statistics_ =
Niels Möller0d210ee2019-08-07 16:16:45 +0200155 ReceiveStatistics::Create(Clock::GetRealTimeClock());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200156 rtp_video_stream_receiver_ = std::make_unique<RtpVideoStreamReceiver>(
Niels Möller60f4e292019-05-20 11:06:33 +0200157 Clock::GetRealTimeClock(), &mock_transport_, nullptr, nullptr, &config_,
158 rtp_receive_statistics_.get(), nullptr, process_thread_.get(),
Niels Möller2f5554d2019-05-29 13:35:14 +0200159 &mock_nack_sender_, &mock_key_frame_request_sender_,
160 &mock_on_complete_frame_callback_, nullptr);
johan62d02c32017-01-24 04:38:27 -0800161 }
162
Niels Möller125b5d62019-03-11 16:11:07 +0100163 RTPVideoHeader GetDefaultH264VideoHeader() {
164 RTPVideoHeader video_header;
165 video_header.codec = kVideoCodecH264;
166 video_header.video_type_header.emplace<RTPVideoHeaderH264>();
167 return video_header;
johan62d02c32017-01-24 04:38:27 -0800168 }
169
170 // TODO(Johan): refactor h264_sps_pps_tracker_unittests.cc to avoid duplicate
171 // code.
Niels Möller125b5d62019-03-11 16:11:07 +0100172 void AddSps(RTPVideoHeader* video_header,
philipel83c97da2017-06-21 07:22:40 -0700173 uint8_t sps_id,
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100174 rtc::CopyOnWriteBuffer* data) {
johan62d02c32017-01-24 04:38:27 -0800175 NaluInfo info;
176 info.type = H264::NaluType::kSps;
177 info.sps_id = sps_id;
178 info.pps_id = -1;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100179 data->AppendData({H264::NaluType::kSps, sps_id});
Niels Möller125b5d62019-03-11 16:11:07 +0100180 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200181 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800182 }
183
Niels Möller125b5d62019-03-11 16:11:07 +0100184 void AddPps(RTPVideoHeader* video_header,
philipel83c97da2017-06-21 07:22:40 -0700185 uint8_t sps_id,
186 uint8_t pps_id,
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100187 rtc::CopyOnWriteBuffer* data) {
johan62d02c32017-01-24 04:38:27 -0800188 NaluInfo info;
189 info.type = H264::NaluType::kPps;
190 info.sps_id = sps_id;
191 info.pps_id = pps_id;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100192 data->AppendData({H264::NaluType::kPps, pps_id});
Niels Möller125b5d62019-03-11 16:11:07 +0100193 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200194 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800195 }
196
Niels Möller125b5d62019-03-11 16:11:07 +0100197 void AddIdr(RTPVideoHeader* video_header, int pps_id) {
johan62d02c32017-01-24 04:38:27 -0800198 NaluInfo info;
199 info.type = H264::NaluType::kIdr;
200 info.sps_id = -1;
201 info.pps_id = pps_id;
Niels Möller125b5d62019-03-11 16:11:07 +0100202 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
philipel7d745e52018-08-02 14:03:53 +0200203 h264.nalus[h264.nalus_length++] = info;
johan62d02c32017-01-24 04:38:27 -0800204 }
205
206 protected:
207 static VideoReceiveStream::Config CreateConfig() {
208 VideoReceiveStream::Config config(nullptr);
209 config.rtp.remote_ssrc = 1111;
210 config.rtp.local_ssrc = 2222;
211 return config;
212 }
213
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100214 const webrtc::test::ScopedFieldTrials override_field_trials_;
johan62d02c32017-01-24 04:38:27 -0800215 VideoReceiveStream::Config config_;
216 MockNackSender mock_nack_sender_;
Niels Möller2f5554d2019-05-29 13:35:14 +0200217 MockKeyFrameRequestSender mock_key_frame_request_sender_;
johan62d02c32017-01-24 04:38:27 -0800218 MockTransport mock_transport_;
219 MockOnCompleteFrameCallback mock_on_complete_frame_callback_;
johan62d02c32017-01-24 04:38:27 -0800220 std::unique_ptr<ProcessThread> process_thread_;
nisseca5706d2017-09-11 02:32:16 -0700221 std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
nisseb1f2ff92017-06-09 04:01:55 -0700222 std::unique_ptr<RtpVideoStreamReceiver> rtp_video_stream_receiver_;
johan62d02c32017-01-24 04:38:27 -0800223};
224
Johannes Krond51ec582019-04-15 13:32:41 +0200225TEST_F(RtpVideoStreamReceiverTest, CacheColorSpaceFromLastPacketOfKeyframe) {
226 // Test that color space is cached from the last packet of a key frame and
227 // that it's not reset by padding packets without color space.
228 constexpr int kPayloadType = 99;
229 const ColorSpace kColorSpace(
230 ColorSpace::PrimaryID::kFILM, ColorSpace::TransferID::kBT2020_12,
231 ColorSpace::MatrixID::kBT2020_NCL, ColorSpace::RangeID::kFull);
232 const std::vector<uint8_t> kKeyFramePayload = {0, 1, 2, 3, 4, 5,
233 6, 7, 8, 9, 10};
234 const std::vector<uint8_t> kDeltaFramePayload = {0, 1, 2, 3, 4};
235
236 // Anonymous helper class that generates received packets.
237 class {
238 public:
239 void SetPayload(const std::vector<uint8_t>& payload,
240 VideoFrameType video_frame_type) {
241 video_frame_type_ = video_frame_type;
242 RtpPacketizer::PayloadSizeLimits pay_load_size_limits;
243 // Reduce max payload length to make sure the key frame generates two
244 // packets.
245 pay_load_size_limits.max_payload_len = 8;
Johannes Krond51ec582019-04-15 13:32:41 +0200246 RTPVideoHeaderVP9 rtp_video_header_vp9;
247 rtp_video_header_vp9.InitRTPVideoHeaderVP9();
248 rtp_video_header_vp9.inter_pic_predicted =
249 (video_frame_type == VideoFrameType::kVideoFrameDelta);
Danil Chapovalov51bf2002019-10-11 10:53:27 +0200250 rtp_packetizer_ = std::make_unique<RtpPacketizerVp9>(
251 payload, pay_load_size_limits, rtp_video_header_vp9);
Johannes Krond51ec582019-04-15 13:32:41 +0200252 }
253
254 size_t NumPackets() { return rtp_packetizer_->NumPackets(); }
255 void SetColorSpace(const ColorSpace& color_space) {
256 color_space_ = color_space;
257 }
258
259 RtpPacketReceived NextPacket() {
260 RtpHeaderExtensionMap extension_map;
261 extension_map.Register<ColorSpaceExtension>(1);
262 RtpPacketToSend packet_to_send(&extension_map);
263 packet_to_send.SetSequenceNumber(sequence_number_++);
264 packet_to_send.SetSsrc(kSsrc);
265 packet_to_send.SetPayloadType(kPayloadType);
266 bool include_color_space =
267 (rtp_packetizer_->NumPackets() == 1u &&
268 video_frame_type_ == VideoFrameType::kVideoFrameKey);
269 if (include_color_space) {
270 EXPECT_TRUE(
271 packet_to_send.SetExtension<ColorSpaceExtension>(color_space_));
272 }
273 rtp_packetizer_->NextPacket(&packet_to_send);
274
275 RtpPacketReceived received_packet(&extension_map);
276 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
277 return received_packet;
278 }
279
280 private:
281 uint16_t sequence_number_ = 0;
282 VideoFrameType video_frame_type_;
283 ColorSpace color_space_;
284 std::unique_ptr<RtpPacketizer> rtp_packetizer_;
285 } received_packet_generator;
286 received_packet_generator.SetColorSpace(kColorSpace);
287
288 // Prepare the receiver for VP9.
289 VideoCodec codec;
290 codec.plType = kPayloadType;
291 codec.codecType = kVideoCodecVP9;
292 std::map<std::string, std::string> codec_params;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200293 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
294 /*raw_payload=*/false);
Johannes Krond51ec582019-04-15 13:32:41 +0200295
296 // Generate key frame packets.
297 received_packet_generator.SetPayload(kKeyFramePayload,
298 VideoFrameType::kVideoFrameKey);
299 EXPECT_EQ(received_packet_generator.NumPackets(), 2u);
300 RtpPacketReceived key_frame_packet1 = received_packet_generator.NextPacket();
301 RtpPacketReceived key_frame_packet2 = received_packet_generator.NextPacket();
302
303 // Generate delta frame packet.
304 received_packet_generator.SetPayload(kDeltaFramePayload,
305 VideoFrameType::kVideoFrameDelta);
306 EXPECT_EQ(received_packet_generator.NumPackets(), 1u);
307 RtpPacketReceived delta_frame_packet = received_packet_generator.NextPacket();
308
309 rtp_video_stream_receiver_->StartReceive();
310 mock_on_complete_frame_callback_.AppendExpectedBitstream(
311 kKeyFramePayload.data(), kKeyFramePayload.size());
312
313 // Send the key frame and expect a callback with color space information.
314 EXPECT_FALSE(key_frame_packet1.GetExtension<ColorSpaceExtension>());
315 EXPECT_TRUE(key_frame_packet2.GetExtension<ColorSpaceExtension>());
316 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
317 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
318 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
319 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
320 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
321 }));
322 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet2);
323 // Resend the first key frame packet to simulate padding for example.
324 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
325
326 mock_on_complete_frame_callback_.ClearExpectedBitstream();
327 mock_on_complete_frame_callback_.AppendExpectedBitstream(
328 kDeltaFramePayload.data(), kDeltaFramePayload.size());
329
330 // Expect delta frame to have color space set even though color space not
331 // included in the RTP packet.
332 EXPECT_FALSE(delta_frame_packet.GetExtension<ColorSpaceExtension>());
333 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
334 .WillOnce(Invoke([kColorSpace](video_coding::EncodedFrame* frame) {
335 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
336 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
337 }));
338 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
339}
340
nisseb1f2ff92017-06-09 04:01:55 -0700341TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrame) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200342 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100343 RTPVideoHeader video_header;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100344 rtc::CopyOnWriteBuffer data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200345 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100346 video_header.is_first_packet_in_frame = true;
347 video_header.is_last_packet_in_frame = true;
348 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200349 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800350 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
351 data.size());
352 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200353 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
354 video_header);
johan62d02c32017-01-24 04:38:27 -0800355}
356
Ruslan Burakovd08bb1e2019-11-27 16:49:10 +0100357TEST_F(RtpVideoStreamReceiverTest, PacketInfoIsPropagatedIntoVideoFrames) {
358 constexpr uint64_t kAbsoluteCaptureTimestamp = 12;
359 constexpr int kId0 = 1;
360
361 RtpHeaderExtensionMap extension_map;
362 extension_map.Register<AbsoluteCaptureTimeExtension>(kId0);
363 RtpPacketReceived rtp_packet(&extension_map);
364 RTPVideoHeader video_header;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100365 rtc::CopyOnWriteBuffer data({1, 2, 3, 4});
Ruslan Burakovd08bb1e2019-11-27 16:49:10 +0100366 rtp_packet.SetSequenceNumber(1);
367 rtp_packet.SetTimestamp(1);
368 rtp_packet.SetSsrc(kSsrc);
369 rtp_packet.SetExtension<AbsoluteCaptureTimeExtension>(
370 AbsoluteCaptureTime{kAbsoluteCaptureTimestamp,
371 /*estimated_capture_clock_offset=*/absl::nullopt});
372
373 video_header.is_first_packet_in_frame = true;
374 video_header.is_last_packet_in_frame = true;
375 video_header.codec = kVideoCodecGeneric;
376 video_header.frame_type = VideoFrameType::kVideoFrameKey;
377 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
378 data.size());
379 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
380 .WillOnce(Invoke(
381 [kAbsoluteCaptureTimestamp](video_coding::EncodedFrame* frame) {
382 EXPECT_THAT(GetAbsoluteCaptureTimestamps(frame),
383 ElementsAre(kAbsoluteCaptureTimestamp));
384 }));
385 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
386 video_header);
387}
388
389TEST_F(RtpVideoStreamReceiverTest,
390 MissingAbsoluteCaptureTimeIsFilledWithExtrapolatedValue) {
391 constexpr uint64_t kAbsoluteCaptureTimestamp = 12;
392 constexpr int kId0 = 1;
393
394 RtpHeaderExtensionMap extension_map;
395 extension_map.Register<AbsoluteCaptureTimeExtension>(kId0);
396 RtpPacketReceived rtp_packet(&extension_map);
397
398 RTPVideoHeader video_header;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100399 rtc::CopyOnWriteBuffer data({1, 2, 3, 4});
Ruslan Burakovd08bb1e2019-11-27 16:49:10 +0100400 uint16_t sequence_number = 1;
401 uint32_t rtp_timestamp = 1;
402 rtp_packet.SetSequenceNumber(sequence_number);
403 rtp_packet.SetTimestamp(rtp_timestamp);
404 rtp_packet.SetSsrc(kSsrc);
405 rtp_packet.SetExtension<AbsoluteCaptureTimeExtension>(
406 AbsoluteCaptureTime{kAbsoluteCaptureTimestamp,
407 /*estimated_capture_clock_offset=*/absl::nullopt});
408
409 video_header.is_first_packet_in_frame = true;
410 video_header.is_last_packet_in_frame = true;
411 video_header.codec = kVideoCodecGeneric;
412 video_header.frame_type = VideoFrameType::kVideoFrameKey;
413 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
414 data.size());
415 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
416 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
417 video_header);
418
419 // Rtp packet without absolute capture time.
420 rtp_packet = RtpPacketReceived(&extension_map);
421 rtp_packet.SetSequenceNumber(++sequence_number);
422 rtp_packet.SetTimestamp(++rtp_timestamp);
423 rtp_packet.SetSsrc(kSsrc);
424
425 // There is no absolute capture time in the second packet.
426 // Expect rtp video stream receiver to extrapolate it for the resulting video
427 // frame using absolute capture time from the previous packet.
428 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
429 .WillOnce(Invoke([](video_coding::EncodedFrame* frame) {
430 EXPECT_THAT(GetAbsoluteCaptureTimestamps(frame), SizeIs(1));
431 }));
432 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
433 video_header);
434}
435
philipeld8f6c162018-01-19 14:41:41 +0100436TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
437 const uint8_t kRedPayloadType = 125;
438 VideoCodec codec;
439 codec.plType = kRedPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200440 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200441 const std::vector<uint8_t> data({
442 0x80, // RTP version.
443 kRedPayloadType, // Payload type.
444 0, 0, 0, 0, 0, 0, // Don't care.
445 0, 0, 0x4, 0x57, // SSRC
446 kRedPayloadType, // RED header.
447 0, 0, 0, 0, 0 // Don't care.
448 });
philipeld8f6c162018-01-19 14:41:41 +0100449 RtpPacketReceived packet;
450 EXPECT_TRUE(packet.Parse(data.data(), data.size()));
451 rtp_video_stream_receiver_->StartReceive();
452 rtp_video_stream_receiver_->OnRtpPacket(packet);
453}
454
Danil Chapovalova715f282018-07-11 17:50:41 +0200455TEST_F(RtpVideoStreamReceiverTest,
456 DropsPacketWithRedPayloadTypeAndEmptyPayload) {
457 const uint8_t kRedPayloadType = 125;
458 config_.rtp.red_payload_type = kRedPayloadType;
459 SetUp(); // re-create rtp_video_stream_receiver with red payload type.
460 // clang-format off
461 const uint8_t data[] = {
462 0x80, // RTP version.
463 kRedPayloadType, // Payload type.
464 0, 0, 0, 0, 0, 0, // Don't care.
465 0, 0, 0x4, 0x57, // SSRC
466 // Empty rtp payload.
467 };
468 // clang-format on
469 RtpPacketReceived packet;
470 // Manually convert to CopyOnWriteBuffer to be sure capacity == size
471 // and asan bot can catch read buffer overflow.
472 EXPECT_TRUE(packet.Parse(rtc::CopyOnWriteBuffer(data)));
473 rtp_video_stream_receiver_->StartReceive();
474 rtp_video_stream_receiver_->OnRtpPacket(packet);
475 // Expect asan doesn't find anything.
476}
477
nisseb1f2ff92017-06-09 04:01:55 -0700478TEST_F(RtpVideoStreamReceiverTest, GenericKeyFrameBitstreamError) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200479 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100480 RTPVideoHeader video_header;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100481 rtc::CopyOnWriteBuffer data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200482 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100483 video_header.is_first_packet_in_frame = true;
484 video_header.is_last_packet_in_frame = true;
485 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200486 video_header.frame_type = VideoFrameType::kVideoFrameKey;
johan62d02c32017-01-24 04:38:27 -0800487 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
488 mock_on_complete_frame_callback_.AppendExpectedBitstream(
489 expected_bitsteam, sizeof(expected_bitsteam));
490 EXPECT_CALL(mock_on_complete_frame_callback_,
491 DoOnCompleteFrameFailBitstream(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200492 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
493 video_header);
johan62d02c32017-01-24 04:38:27 -0800494}
495
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100496class RtpVideoStreamReceiverTestH264
497 : public RtpVideoStreamReceiverTest,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200498 public ::testing::WithParamInterface<std::string> {
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100499 protected:
500 RtpVideoStreamReceiverTestH264() : RtpVideoStreamReceiverTest(GetParam()) {}
501};
502
Elad Alonccb9b752019-02-19 13:01:31 +0100503INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframe,
504 RtpVideoStreamReceiverTestH264,
505 Values("", "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100506
507TEST_P(RtpVideoStreamReceiverTestH264, InBandSpsPps) {
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100508 rtc::CopyOnWriteBuffer sps_data;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200509 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100510 RTPVideoHeader sps_video_header = GetDefaultH264VideoHeader();
511 AddSps(&sps_video_header, 0, &sps_data);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200512 rtp_packet.SetSequenceNumber(0);
Niels Möller125b5d62019-03-11 16:11:07 +0100513 sps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200514 sps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800515 mock_on_complete_frame_callback_.AppendExpectedBitstream(
516 kH264StartCode, sizeof(kH264StartCode));
517 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
518 sps_data.size());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200519 rtp_video_stream_receiver_->OnReceivedPayloadData(sps_data, rtp_packet,
520 sps_video_header);
johan62d02c32017-01-24 04:38:27 -0800521
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100522 rtc::CopyOnWriteBuffer pps_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100523 RTPVideoHeader pps_video_header = GetDefaultH264VideoHeader();
524 AddPps(&pps_video_header, 0, 1, &pps_data);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200525 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100526 pps_video_header.is_first_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200527 pps_video_header.frame_type = VideoFrameType::kEmptyFrame;
johan62d02c32017-01-24 04:38:27 -0800528 mock_on_complete_frame_callback_.AppendExpectedBitstream(
529 kH264StartCode, sizeof(kH264StartCode));
530 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
531 pps_data.size());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200532 rtp_video_stream_receiver_->OnReceivedPayloadData(pps_data, rtp_packet,
533 pps_video_header);
johan62d02c32017-01-24 04:38:27 -0800534
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100535 rtc::CopyOnWriteBuffer idr_data;
Niels Möller125b5d62019-03-11 16:11:07 +0100536 RTPVideoHeader idr_video_header = GetDefaultH264VideoHeader();
537 AddIdr(&idr_video_header, 1);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200538 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100539 idr_video_header.is_first_packet_in_frame = true;
540 idr_video_header.is_last_packet_in_frame = true;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200541 idr_video_header.frame_type = VideoFrameType::kVideoFrameKey;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100542 const uint8_t idr[] = {0x65, 1, 2, 3};
543 idr_data.AppendData(idr);
johan62d02c32017-01-24 04:38:27 -0800544 mock_on_complete_frame_callback_.AppendExpectedBitstream(
545 kH264StartCode, sizeof(kH264StartCode));
546 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
547 idr_data.size());
548 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200549 rtp_video_stream_receiver_->OnReceivedPayloadData(idr_data, rtp_packet,
550 idr_video_header);
johan62d02c32017-01-24 04:38:27 -0800551}
552
Rasmus Brandt88f080a2017-11-02 14:28:06 +0100553TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) {
johan62d02c32017-01-24 04:38:27 -0800554 constexpr int kPayloadType = 99;
555 VideoCodec codec;
556 codec.plType = kPayloadType;
557 std::map<std::string, std::string> codec_params;
558 // Example parameter sets from https://tools.ietf.org/html/rfc3984#section-8.2
559 // .
560 codec_params.insert(
561 {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="});
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200562 rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params,
563 /*raw_payload=*/false);
johan62d02c32017-01-24 04:38:27 -0800564 const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
565 0x53, 0x05, 0x89, 0x88};
566 mock_on_complete_frame_callback_.AppendExpectedBitstream(
567 kH264StartCode, sizeof(kH264StartCode));
568 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_sps,
569 sizeof(binary_sps));
570 const uint8_t binary_pps[] = {0x68, 0xc9, 0x63, 0x88};
571 mock_on_complete_frame_callback_.AppendExpectedBitstream(
572 kH264StartCode, sizeof(kH264StartCode));
573 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_pps,
574 sizeof(binary_pps));
575
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200576 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100577 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
578 AddIdr(&video_header, 0);
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200579 rtp_packet.SetPayloadType(kPayloadType);
580 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100581 video_header.is_first_packet_in_frame = true;
582 video_header.is_last_packet_in_frame = true;
583 video_header.codec = kVideoCodecH264;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200584 video_header.frame_type = VideoFrameType::kVideoFrameKey;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100585 rtc::CopyOnWriteBuffer data({1, 2, 3});
johan62d02c32017-01-24 04:38:27 -0800586 mock_on_complete_frame_callback_.AppendExpectedBitstream(
587 kH264StartCode, sizeof(kH264StartCode));
588 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
589 data.size());
590 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200591 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
592 video_header);
johan62d02c32017-01-24 04:38:27 -0800593}
594
nisseb1f2ff92017-06-09 04:01:55 -0700595TEST_F(RtpVideoStreamReceiverTest, PaddingInMediaStream) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200596 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100597 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100598 rtc::CopyOnWriteBuffer data({1, 2, 3});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200599 rtp_packet.SetPayloadType(99);
600 rtp_packet.SetSequenceNumber(2);
Niels Möller125b5d62019-03-11 16:11:07 +0100601 video_header.is_first_packet_in_frame = true;
602 video_header.is_last_packet_in_frame = true;
603 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200604 video_header.frame_type = VideoFrameType::kVideoFrameKey;
philipel54ca9192017-03-21 05:45:18 -0700605 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
606 data.size());
607
608 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200609 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
610 video_header);
philipel54ca9192017-03-21 05:45:18 -0700611
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200612 rtp_packet.SetSequenceNumber(3);
613 rtp_video_stream_receiver_->OnReceivedPayloadData({}, rtp_packet,
614 video_header);
philipel54ca9192017-03-21 05:45:18 -0700615
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200616 rtp_packet.SetSequenceNumber(4);
philipel54ca9192017-03-21 05:45:18 -0700617 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Niels Möllerabbc50e2019-04-24 09:41:16 +0200618 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200619 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
620 video_header);
philipel54ca9192017-03-21 05:45:18 -0700621
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200622 rtp_packet.SetSequenceNumber(6);
623 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
624 video_header);
philipel54ca9192017-03-21 05:45:18 -0700625
626 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200627 rtp_packet.SetSequenceNumber(5);
628 rtp_video_stream_receiver_->OnReceivedPayloadData({}, rtp_packet,
629 video_header);
philipel54ca9192017-03-21 05:45:18 -0700630}
631
nisseb1f2ff92017-06-09 04:01:55 -0700632TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeIfFirstFrameIsDelta) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200633 RtpPacketReceived rtp_packet;
Niels Möller125b5d62019-03-11 16:11:07 +0100634 RTPVideoHeader video_header;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100635 rtc::CopyOnWriteBuffer data({1, 2, 3, 4});
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200636 rtp_packet.SetSequenceNumber(1);
Niels Möller125b5d62019-03-11 16:11:07 +0100637 video_header.is_first_packet_in_frame = true;
638 video_header.is_last_packet_in_frame = true;
639 video_header.codec = kVideoCodecGeneric;
Niels Möllerabbc50e2019-04-24 09:41:16 +0200640 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
Niels Möller2f5554d2019-05-29 13:35:14 +0200641 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200642 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
643 video_header);
philipel2c53b132017-05-16 08:06:30 -0700644}
645
Johannes Kronbd3f3052019-08-01 15:45:54 +0200646TEST_F(RtpVideoStreamReceiverTest, RequestKeyframeWhenPacketBufferGetsFull) {
647 constexpr int kPacketBufferMaxSize = 2048;
648
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200649 RtpPacketReceived rtp_packet;
Johannes Kronbd3f3052019-08-01 15:45:54 +0200650 RTPVideoHeader video_header;
Danil Chapovalovcebdbf62019-12-13 16:08:18 +0100651 rtc::CopyOnWriteBuffer data({1, 2, 3, 4});
Johannes Kronbd3f3052019-08-01 15:45:54 +0200652 video_header.is_first_packet_in_frame = true;
653 // Incomplete frames so that the packet buffer is filling up.
654 video_header.is_last_packet_in_frame = false;
655 video_header.codec = kVideoCodecGeneric;
656 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
657 uint16_t start_sequence_number = 1234;
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200658 rtp_packet.SetSequenceNumber(start_sequence_number);
659 while (rtp_packet.SequenceNumber() - start_sequence_number <
Johannes Kronbd3f3052019-08-01 15:45:54 +0200660 kPacketBufferMaxSize) {
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200661 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
662 video_header);
663 rtp_packet.SetSequenceNumber(rtp_packet.SequenceNumber() + 2);
Johannes Kronbd3f3052019-08-01 15:45:54 +0200664 }
665
666 EXPECT_CALL(mock_key_frame_request_sender_, RequestKeyFrame());
Danil Chapovalovc71d85b2019-10-16 19:18:21 +0200667 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
668 video_header);
Johannes Kronbd3f3052019-08-01 15:45:54 +0200669}
670
eladalonc0d481a2017-08-02 07:39:07 -0700671TEST_F(RtpVideoStreamReceiverTest, SecondarySinksGetRtpNotifications) {
672 rtp_video_stream_receiver_->StartReceive();
673
674 MockRtpPacketSink secondary_sink_1;
675 MockRtpPacketSink secondary_sink_2;
676
677 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_1);
678 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink_2);
679
680 auto rtp_packet = CreateRtpPacketReceived();
681 EXPECT_CALL(secondary_sink_1, OnRtpPacket(SamePacketAs(*rtp_packet)));
682 EXPECT_CALL(secondary_sink_2, OnRtpPacket(SamePacketAs(*rtp_packet)));
683
684 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
685
686 // Test tear-down.
687 rtp_video_stream_receiver_->StopReceive();
688 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_1);
689 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink_2);
690}
691
692TEST_F(RtpVideoStreamReceiverTest, RemovedSecondarySinksGetNoRtpNotifications) {
693 rtp_video_stream_receiver_->StartReceive();
694
695 MockRtpPacketSink secondary_sink;
696
697 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
698 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
699
700 auto rtp_packet = CreateRtpPacketReceived();
701
702 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
703
704 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
705
706 // Test tear-down.
707 rtp_video_stream_receiver_->StopReceive();
708}
709
710TEST_F(RtpVideoStreamReceiverTest,
711 OnlyRemovedSecondarySinksExcludedFromNotifications) {
712 rtp_video_stream_receiver_->StartReceive();
713
714 MockRtpPacketSink kept_secondary_sink;
715 MockRtpPacketSink removed_secondary_sink;
716
717 rtp_video_stream_receiver_->AddSecondarySink(&kept_secondary_sink);
718 rtp_video_stream_receiver_->AddSecondarySink(&removed_secondary_sink);
719 rtp_video_stream_receiver_->RemoveSecondarySink(&removed_secondary_sink);
720
721 auto rtp_packet = CreateRtpPacketReceived();
722 EXPECT_CALL(kept_secondary_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
723
724 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
725
726 // Test tear-down.
727 rtp_video_stream_receiver_->StopReceive();
728 rtp_video_stream_receiver_->RemoveSecondarySink(&kept_secondary_sink);
729}
730
731TEST_F(RtpVideoStreamReceiverTest,
732 SecondariesOfNonStartedStreamGetNoNotifications) {
733 // Explicitly showing that the stream is not in the |started| state,
734 // regardless of whether streams start out |started| or |stopped|.
735 rtp_video_stream_receiver_->StopReceive();
736
737 MockRtpPacketSink secondary_sink;
738 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
739
740 auto rtp_packet = CreateRtpPacketReceived();
741 EXPECT_CALL(secondary_sink, OnRtpPacket(_)).Times(0);
742
743 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
744
745 // Test tear-down.
746 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
747}
748
Elad Alonccb9b752019-02-19 13:01:31 +0100749class RtpVideoStreamReceiverGenericDescriptorTest
750 : public RtpVideoStreamReceiverTest,
751 public ::testing::WithParamInterface<int> {
752 public:
753 void RegisterRtpGenericFrameDescriptorExtension(
754 RtpHeaderExtensionMap* extension_map,
755 int version) {
756 constexpr int kId00 = 5;
757 constexpr int kId01 = 6;
758 switch (version) {
759 case 0:
760 extension_map->Register<RtpGenericFrameDescriptorExtension00>(kId00);
761 return;
762 case 1:
763 extension_map->Register<RtpGenericFrameDescriptorExtension01>(kId01);
764 return;
765 }
766 RTC_NOTREACHED();
767 }
768
769 bool SetExtensionRtpGenericFrameDescriptorExtension(
770 const RtpGenericFrameDescriptor& generic_descriptor,
771 RtpPacketReceived* rtp_packet,
772 int version) {
773 switch (version) {
774 case 0:
775 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension00>(
776 generic_descriptor);
777 case 1:
778 return rtp_packet->SetExtension<RtpGenericFrameDescriptorExtension01>(
779 generic_descriptor);
780 }
781 RTC_NOTREACHED();
782 return false;
783 }
784};
785
Mirko Bonadei1b575412019-09-23 08:34:50 +0200786INSTANTIATE_TEST_SUITE_P(All,
Elad Alonccb9b752019-02-19 13:01:31 +0100787 RtpVideoStreamReceiverGenericDescriptorTest,
788 Values(0, 1));
789
790TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
791 ParseGenericDescriptorOnePacket) {
792 const int version = GetParam();
793
philipeldabfcae2018-09-25 12:54:37 +0200794 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
795 const int kPayloadType = 123;
796 const int kSpatialIndex = 1;
797
798 VideoCodec codec;
799 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200800 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200801 rtp_video_stream_receiver_->StartReceive();
802
803 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100804 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200805 RtpPacketReceived rtp_packet(&extension_map);
806
807 RtpGenericFrameDescriptor generic_descriptor;
808 generic_descriptor.SetFirstPacketInSubFrame(true);
809 generic_descriptor.SetLastPacketInSubFrame(true);
philipeldabfcae2018-09-25 12:54:37 +0200810 generic_descriptor.SetFrameId(100);
811 generic_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
812 generic_descriptor.AddFrameDependencyDiff(90);
813 generic_descriptor.AddFrameDependencyDiff(80);
Elad Alonccb9b752019-02-19 13:01:31 +0100814 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
815 generic_descriptor, &rtp_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200816
817 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
818 memcpy(payload, data.data(), data.size());
819 // The first byte is the header, so we ignore the first byte of |data|.
820 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
821 data.size() - 1);
822
823 rtp_packet.SetMarker(true);
824 rtp_packet.SetPayloadType(kPayloadType);
825 rtp_packet.SetSequenceNumber(1);
826
827 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
828 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
829 EXPECT_EQ(frame->num_references, 2U);
830 EXPECT_EQ(frame->references[0], frame->id.picture_id - 90);
831 EXPECT_EQ(frame->references[1], frame->id.picture_id - 80);
832 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
Chen Xingf00bf422019-06-20 10:05:55 +0200833 EXPECT_THAT(frame->PacketInfos(), SizeIs(1));
philipeldabfcae2018-09-25 12:54:37 +0200834 }));
835
836 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
837}
838
Elad Alonccb9b752019-02-19 13:01:31 +0100839TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
840 ParseGenericDescriptorTwoPackets) {
841 const int version = GetParam();
842
philipeldabfcae2018-09-25 12:54:37 +0200843 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
844 const int kPayloadType = 123;
845 const int kSpatialIndex = 1;
846
847 VideoCodec codec;
848 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200849 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
philipeldabfcae2018-09-25 12:54:37 +0200850 rtp_video_stream_receiver_->StartReceive();
851
852 RtpHeaderExtensionMap extension_map;
Elad Alonccb9b752019-02-19 13:01:31 +0100853 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
philipeldabfcae2018-09-25 12:54:37 +0200854 RtpPacketReceived first_packet(&extension_map);
855
856 RtpGenericFrameDescriptor first_packet_descriptor;
857 first_packet_descriptor.SetFirstPacketInSubFrame(true);
858 first_packet_descriptor.SetLastPacketInSubFrame(false);
philipeldabfcae2018-09-25 12:54:37 +0200859 first_packet_descriptor.SetFrameId(100);
philipeldabfcae2018-09-25 12:54:37 +0200860 first_packet_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200861 first_packet_descriptor.SetResolution(480, 360);
Elad Alonccb9b752019-02-19 13:01:31 +0100862 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
863 first_packet_descriptor, &first_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200864
865 uint8_t* first_packet_payload = first_packet.SetPayloadSize(data.size());
866 memcpy(first_packet_payload, data.data(), data.size());
867 // The first byte is the header, so we ignore the first byte of |data|.
868 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
869 data.size() - 1);
870
871 first_packet.SetPayloadType(kPayloadType);
872 first_packet.SetSequenceNumber(1);
873 rtp_video_stream_receiver_->OnRtpPacket(first_packet);
874
875 RtpPacketReceived second_packet(&extension_map);
876 RtpGenericFrameDescriptor second_packet_descriptor;
877 second_packet_descriptor.SetFirstPacketInSubFrame(false);
878 second_packet_descriptor.SetLastPacketInSubFrame(true);
Elad Alonccb9b752019-02-19 13:01:31 +0100879 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
880 second_packet_descriptor, &second_packet, version));
philipeldabfcae2018-09-25 12:54:37 +0200881
882 second_packet.SetMarker(true);
883 second_packet.SetPayloadType(kPayloadType);
884 second_packet.SetSequenceNumber(2);
885
886 uint8_t* second_packet_payload = second_packet.SetPayloadSize(data.size());
887 memcpy(second_packet_payload, data.data(), data.size());
888 // The first byte is the header, so we ignore the first byte of |data|.
889 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
890 data.size() - 1);
891
892 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
893 .WillOnce(Invoke([kSpatialIndex](video_coding::EncodedFrame* frame) {
philipelfab91292018-10-17 14:36:08 +0200894 EXPECT_EQ(frame->num_references, 0U);
philipeldabfcae2018-09-25 12:54:37 +0200895 EXPECT_EQ(frame->id.spatial_layer, kSpatialIndex);
philipelfab91292018-10-17 14:36:08 +0200896 EXPECT_EQ(frame->EncodedImage()._encodedWidth, 480u);
897 EXPECT_EQ(frame->EncodedImage()._encodedHeight, 360u);
Chen Xingf00bf422019-06-20 10:05:55 +0200898 EXPECT_THAT(frame->PacketInfos(), SizeIs(2));
philipeldabfcae2018-09-25 12:54:37 +0200899 }));
900
901 rtp_video_stream_receiver_->OnRtpPacket(second_packet);
902}
903
Elad Alonccb9b752019-02-19 13:01:31 +0100904TEST_F(RtpVideoStreamReceiverGenericDescriptorTest,
905 DropPacketsWithMultipleVersionsOfExtension) {
906 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
907 const int kPayloadType = 123;
908
909 VideoCodec codec;
910 codec.plType = kPayloadType;
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200911 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
Elad Alonccb9b752019-02-19 13:01:31 +0100912 rtp_video_stream_receiver_->StartReceive();
913
914 RtpHeaderExtensionMap extension_map;
915 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 0);
916 RegisterRtpGenericFrameDescriptorExtension(&extension_map, 1);
917 RtpPacketReceived rtp_packet(&extension_map);
918
919 RtpGenericFrameDescriptor generic_descriptors[2];
920 for (size_t i = 0; i < 2; ++i) {
921 generic_descriptors[i].SetFirstPacketInSubFrame(true);
922 generic_descriptors[i].SetLastPacketInSubFrame(true);
923 generic_descriptors[i].SetFrameId(100);
924 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
925 generic_descriptors[i], &rtp_packet, i));
926 }
927
928 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
929 memcpy(payload, data.data(), data.size());
930 // The first byte is the header, so we ignore the first byte of |data|.
931 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
932 data.size() - 1);
933
934 rtp_packet.SetMarker(true);
935 rtp_packet.SetPayloadType(kPayloadType);
936 rtp_packet.SetSequenceNumber(1);
937
938 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
939
940 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
941}
942
Mirta Dvornicicfe68daa2019-05-23 13:21:12 +0200943TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
944 ParseGenericDescriptorRawPayload) {
945 const int version = GetParam();
946
947 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
948 const int kPayloadType = 123;
949
950 VideoCodec codec;
951 codec.plType = kPayloadType;
952 rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/true);
953 rtp_video_stream_receiver_->StartReceive();
954
955 RtpHeaderExtensionMap extension_map;
956 RegisterRtpGenericFrameDescriptorExtension(&extension_map, version);
957 RtpPacketReceived rtp_packet(&extension_map);
958
959 RtpGenericFrameDescriptor generic_descriptor;
960 generic_descriptor.SetFirstPacketInSubFrame(true);
961 generic_descriptor.SetLastPacketInSubFrame(true);
962 ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension(
963 generic_descriptor, &rtp_packet, version));
964
965 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
966 memcpy(payload, data.data(), data.size());
967 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
968 data.size());
969
970 rtp_packet.SetMarker(true);
971 rtp_packet.SetPayloadType(kPayloadType);
972 rtp_packet.SetSequenceNumber(1);
973
974 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
975 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
976}
977
eladalonc0d481a2017-08-02 07:39:07 -0700978#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
979TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
980 MockRtpPacketSink secondary_sink;
981
982 rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink);
983 EXPECT_DEATH(rtp_video_stream_receiver_->AddSecondarySink(&secondary_sink),
984 "");
985
986 // Test tear-down.
987 rtp_video_stream_receiver_->RemoveSecondarySink(&secondary_sink);
988}
989#endif
990
johan62d02c32017-01-24 04:38:27 -0800991} // namespace webrtc