blob: 07c23a4f3398374fb09ffae518ec322a30c86943 [file] [log] [blame]
Tommid3807da2020-05-22 15:36:361/*
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
11#include "video/rtp_video_stream_receiver2.h"
12
13#include <memory>
14#include <utility>
15
Danil Chapovalove2fee232024-08-29 09:50:3316#include "api/environment/environment.h"
17#include "api/environment/environment_factory.h"
Markus Handell885d5382021-06-21 16:57:3618#include "api/task_queue/task_queue_base.h"
Tony Herre9c6874602024-01-26 10:16:4519#include "api/test/mock_frame_transformer.h"
Tommid3807da2020-05-22 15:36:3620#include "api/video/video_codec_type.h"
21#include "api/video/video_frame_type.h"
Danil Chapovalov9cd4d492021-08-03 12:59:0022#include "call/test/mock_rtp_packet_sink_interface.h"
Tommid3807da2020-05-22 15:36:3623#include "common_video/h264/h264_common.h"
24#include "media/base/media_constants.h"
Erik Språng5fc74892024-11-29 11:03:5125#include "modules/rtp_rtcp/source/corruption_detection_extension.h"
Tony Herrebe9b5762023-02-03 11:29:0426#include "modules/rtp_rtcp/source/frame_object.h"
Tommid3807da2020-05-22 15:36:3627#include "modules/rtp_rtcp/source/rtp_descriptor_authentication.h"
28#include "modules/rtp_rtcp/source/rtp_format.h"
29#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
30#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
31#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
32#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
33#include "modules/rtp_rtcp/source/rtp_packet_received.h"
34#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
Tommid3807da2020-05-22 15:36:3635#include "modules/video_coding/include/video_coding_defines.h"
36#include "modules/video_coding/rtp_frame_reference_finder.h"
37#include "rtc_base/byte_buffer.h"
38#include "rtc_base/logging.h"
39#include "system_wrappers/include/clock.h"
Danil Chapovalove2fee232024-08-29 09:50:3340#include "test/explicit_key_value_config.h"
Tommid3807da2020-05-22 15:36:3641#include "test/gmock.h"
42#include "test/gtest.h"
Danil Chapovalov9cd4d492021-08-03 12:59:0043#include "test/mock_transport.h"
philipel27b35a72022-07-05 07:59:5544#include "test/rtcp_packet_parser.h"
Tomas Gunnarssonfae05622020-06-03 06:54:3945#include "test/time_controller/simulated_task_queue.h"
Markus Handell885d5382021-06-21 16:57:3646#include "test/time_controller/simulated_time_controller.h"
Tommid3807da2020-05-22 15:36:3647
Danil Chapovalove2fee232024-08-29 09:50:3348namespace webrtc {
49
50namespace {
51
52using test::ExplicitKeyValueConfig;
Tommid3807da2020-05-22 15:36:3653using ::testing::_;
Erik Språng5fc74892024-11-29 11:03:5154using ::testing::DoubleNear;
Tommid3807da2020-05-22 15:36:3655using ::testing::ElementsAre;
philipel27b35a72022-07-05 07:59:5556using ::testing::Eq;
Tommid3807da2020-05-22 15:36:3657using ::testing::Invoke;
58using ::testing::SizeIs;
59using ::testing::Values;
60
Tommid3807da2020-05-22 15:36:3661const uint8_t kH264StartCode[] = {0x00, 0x00, 0x00, 0x01};
62
Erik Språng5fc74892024-11-29 11:03:5163// Corruption detection metrics for testing.
64constexpr double kStd = 1.0;
65constexpr int kLumaThreshold = 5;
66constexpr int kChormaThreshold = 3;
67constexpr int kVp9PayloadType = 99;
68constexpr int kNumSamples = 13;
69// 8 bits.
70constexpr int kMaxSequenceIdx = 127;
71
philipelca188092021-03-23 11:00:4972std::vector<uint64_t> GetAbsoluteCaptureTimestamps(const EncodedFrame* frame) {
Tommid3807da2020-05-22 15:36:3673 std::vector<uint64_t> result;
74 for (const auto& packet_info : frame->PacketInfos()) {
75 if (packet_info.absolute_capture_time()) {
76 result.push_back(
77 packet_info.absolute_capture_time()->absolute_capture_timestamp);
78 }
79 }
80 return result;
81}
82
83RTPVideoHeader GetGenericVideoHeader(VideoFrameType frame_type) {
84 RTPVideoHeader video_header;
85 video_header.is_first_packet_in_frame = true;
86 video_header.is_last_packet_in_frame = true;
87 video_header.codec = kVideoCodecGeneric;
88 video_header.frame_type = frame_type;
89 return video_header;
90}
91
Tommid3807da2020-05-22 15:36:3692class MockNackSender : public NackSender {
93 public:
94 MOCK_METHOD(void,
95 SendNack,
96 (const std::vector<uint16_t>& sequence_numbers,
97 bool buffering_allowed),
98 (override));
99};
100
101class MockKeyFrameRequestSender : public KeyFrameRequestSender {
102 public:
103 MOCK_METHOD(void, RequestKeyFrame, (), (override));
104};
105
philipel21820962021-05-25 13:35:57106class MockOnCompleteFrameCallback
107 : public RtpVideoStreamReceiver2::OnCompleteFrameCallback {
Tommid3807da2020-05-22 15:36:36108 public:
philipelca188092021-03-23 11:00:49109 MOCK_METHOD(void, DoOnCompleteFrame, (EncodedFrame*), ());
110 MOCK_METHOD(void, DoOnCompleteFrameFailNullptr, (EncodedFrame*), ());
111 MOCK_METHOD(void, DoOnCompleteFrameFailLength, (EncodedFrame*), ());
112 MOCK_METHOD(void, DoOnCompleteFrameFailBitstream, (EncodedFrame*), ());
113 void OnCompleteFrame(std::unique_ptr<EncodedFrame> frame) override {
Tommid3807da2020-05-22 15:36:36114 if (!frame) {
115 DoOnCompleteFrameFailNullptr(nullptr);
116 return;
117 }
118 EXPECT_EQ(buffer_.Length(), frame->size());
119 if (buffer_.Length() != frame->size()) {
120 DoOnCompleteFrameFailLength(frame.get());
121 return;
122 }
123 if (frame->size() != buffer_.Length() ||
124 memcmp(buffer_.Data(), frame->data(), buffer_.Length()) != 0) {
125 DoOnCompleteFrameFailBitstream(frame.get());
126 return;
127 }
128 DoOnCompleteFrame(frame.get());
129 }
130
131 void ClearExpectedBitstream() { buffer_.Clear(); }
132
133 void AppendExpectedBitstream(const uint8_t data[], size_t size_in_bytes) {
134 // TODO(Johan): Let rtc::ByteBuffer handle uint8_t* instead of char*.
Harald Alvestrandf0ddae82023-12-12 12:05:20135 buffer_.WriteBytes(data, size_in_bytes);
Tommid3807da2020-05-22 15:36:36136 }
137 rtc::ByteBufferWriter buffer_;
138};
139
Tommid3807da2020-05-22 15:36:36140constexpr uint32_t kSsrc = 111;
Tommid3807da2020-05-22 15:36:36141constexpr int kPayloadType = 100;
142constexpr int kRedPayloadType = 125;
143
144std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived() {
Tomas Gunnarsson8408c992021-02-14 13:19:12145 constexpr uint16_t kSequenceNumber = 222;
Tommid3807da2020-05-22 15:36:36146 auto packet = std::make_unique<RtpPacketReceived>();
147 packet->SetSsrc(kSsrc);
148 packet->SetSequenceNumber(kSequenceNumber);
149 packet->SetPayloadType(kPayloadType);
150 return packet;
151}
152
153MATCHER_P(SamePacketAs, other, "") {
154 return arg.Ssrc() == other.Ssrc() &&
155 arg.SequenceNumber() == other.SequenceNumber();
156}
157
158} // namespace
159
Tomas Gunnarsson8408c992021-02-14 13:19:12160class RtpVideoStreamReceiver2Test : public ::testing::Test,
161 public RtpPacketSinkInterface {
Tommid3807da2020-05-22 15:36:36162 public:
163 RtpVideoStreamReceiver2Test() : RtpVideoStreamReceiver2Test("") {}
164 explicit RtpVideoStreamReceiver2Test(std::string field_trials)
Markus Handell885d5382021-06-21 16:57:36165 : time_controller_(Timestamp::Millis(100)),
Danil Chapovalove2fee232024-08-29 09:50:33166 env_(CreateEnvironment(
167 std::make_unique<ExplicitKeyValueConfig>(field_trials),
168 time_controller_.GetClock(),
169 time_controller_.GetTaskQueueFactory())),
Markus Handell885d5382021-06-21 16:57:36170 task_queue_(time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
171 "RtpVideoStreamReceiver2Test",
172 TaskQueueFactory::Priority::NORMAL)),
173 task_queue_setter_(task_queue_.get()),
Markus Handelleb61b7f2021-06-22 08:46:48174 config_(CreateConfig()) {
Danil Chapovalove2fee232024-08-29 09:50:33175 rtp_receive_statistics_ = ReceiveStatistics::Create(&env_.clock());
Tommid3807da2020-05-22 15:36:36176 rtp_video_stream_receiver_ = std::make_unique<RtpVideoStreamReceiver2>(
Danil Chapovalove2fee232024-08-29 09:50:33177 env_, TaskQueueBase::Current(), &mock_transport_, nullptr, nullptr,
178 &config_, rtp_receive_statistics_.get(), nullptr, nullptr,
179 &nack_periodic_processor_, &mock_on_complete_frame_callback_, nullptr,
180 nullptr);
Danil Chapovalov5653c952021-08-10 14:57:56181 rtp_video_stream_receiver_->AddReceiveCodec(kPayloadType,
182 kVideoCodecGeneric, {},
Tommid3807da2020-05-22 15:36:36183 /*raw_payload=*/false);
philipel27b35a72022-07-05 07:59:55184 ON_CALL(mock_transport_, SendRtcp)
185 .WillByDefault(
186 Invoke(&rtcp_packet_parser_, &test::RtcpPacketParser::Parse));
Tommid3807da2020-05-22 15:36:36187 }
188
189 RTPVideoHeader GetDefaultH264VideoHeader() {
190 RTPVideoHeader video_header;
191 video_header.codec = kVideoCodecH264;
192 video_header.video_type_header.emplace<RTPVideoHeaderH264>();
193 return video_header;
194 }
195
196 // TODO(Johan): refactor h264_sps_pps_tracker_unittests.cc to avoid duplicate
197 // code.
198 void AddSps(RTPVideoHeader* video_header,
199 uint8_t sps_id,
200 rtc::CopyOnWriteBuffer* data) {
201 NaluInfo info;
202 info.type = H264::NaluType::kSps;
203 info.sps_id = sps_id;
204 info.pps_id = -1;
Andrew Johnsonf288f5b2020-09-19 05:35:59205 data->AppendData<uint8_t, 2>({H264::NaluType::kSps, sps_id});
Tommid3807da2020-05-22 15:36:36206 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
Sergio Garcia Murillo469e6982024-06-14 12:10:50207 h264.nalus.push_back(info);
Tommid3807da2020-05-22 15:36:36208 }
209
210 void AddPps(RTPVideoHeader* video_header,
211 uint8_t sps_id,
212 uint8_t pps_id,
213 rtc::CopyOnWriteBuffer* data) {
214 NaluInfo info;
215 info.type = H264::NaluType::kPps;
216 info.sps_id = sps_id;
217 info.pps_id = pps_id;
Andrew Johnsonf288f5b2020-09-19 05:35:59218 data->AppendData<uint8_t, 2>({H264::NaluType::kPps, pps_id});
Tommid3807da2020-05-22 15:36:36219 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
Sergio Garcia Murillo469e6982024-06-14 12:10:50220 h264.nalus.push_back(info);
Tommid3807da2020-05-22 15:36:36221 }
222
223 void AddIdr(RTPVideoHeader* video_header, int pps_id) {
224 NaluInfo info;
225 info.type = H264::NaluType::kIdr;
226 info.sps_id = -1;
227 info.pps_id = pps_id;
228 auto& h264 = absl::get<RTPVideoHeaderH264>(video_header->video_type_header);
Sergio Garcia Murillo469e6982024-06-14 12:10:50229 h264.nalus.push_back(info);
Tommid3807da2020-05-22 15:36:36230 }
231
Tomas Gunnarsson8408c992021-02-14 13:19:12232 void OnRtpPacket(const RtpPacketReceived& packet) override {
233 if (test_packet_sink_)
234 test_packet_sink_->OnRtpPacket(packet);
235 }
236
Tommid3807da2020-05-22 15:36:36237 protected:
Tommif6f45432022-05-20 13:21:20238 VideoReceiveStreamInterface::Config CreateConfig() {
239 VideoReceiveStreamInterface::Config config(nullptr);
Tommid3807da2020-05-22 15:36:36240 config.rtp.remote_ssrc = 1111;
241 config.rtp.local_ssrc = 2222;
242 config.rtp.red_payload_type = kRedPayloadType;
Tomas Gunnarsson8408c992021-02-14 13:19:12243 config.rtp.packet_sink_ = this;
Tommid3807da2020-05-22 15:36:36244 return config;
245 }
246
Markus Handell885d5382021-06-21 16:57:36247 GlobalSimulatedTimeController time_controller_;
Danil Chapovalove2fee232024-08-29 09:50:33248 Environment env_;
Markus Handell885d5382021-06-21 16:57:36249 std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue_;
250 TokenTaskQueue::CurrentTaskQueueSetter task_queue_setter_;
Tomas Gunnarssonfae05622020-06-03 06:54:39251
Tommif6f45432022-05-20 13:21:20252 VideoReceiveStreamInterface::Config config_;
Markus Handell0e62f7a2021-07-20 11:32:02253 NackPeriodicProcessor nack_periodic_processor_;
philipel27b35a72022-07-05 07:59:55254 test::RtcpPacketParser rtcp_packet_parser_;
Tommid3807da2020-05-22 15:36:36255 MockTransport mock_transport_;
256 MockOnCompleteFrameCallback mock_on_complete_frame_callback_;
Tommid3807da2020-05-22 15:36:36257 std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
258 std::unique_ptr<RtpVideoStreamReceiver2> rtp_video_stream_receiver_;
Tomas Gunnarsson8408c992021-02-14 13:19:12259 RtpPacketSinkInterface* test_packet_sink_ = nullptr;
Tommid3807da2020-05-22 15:36:36260};
261
262TEST_F(RtpVideoStreamReceiver2Test, CacheColorSpaceFromLastPacketOfKeyframe) {
263 // Test that color space is cached from the last packet of a key frame and
264 // that it's not reset by padding packets without color space.
Tommid3807da2020-05-22 15:36:36265 const ColorSpace kColorSpace(
266 ColorSpace::PrimaryID::kFILM, ColorSpace::TransferID::kBT2020_12,
267 ColorSpace::MatrixID::kBT2020_NCL, ColorSpace::RangeID::kFull);
268 const std::vector<uint8_t> kKeyFramePayload = {0, 1, 2, 3, 4, 5,
269 6, 7, 8, 9, 10};
270 const std::vector<uint8_t> kDeltaFramePayload = {0, 1, 2, 3, 4};
271
272 // Anonymous helper class that generates received packets.
273 class {
274 public:
275 void SetPayload(const std::vector<uint8_t>& payload,
276 VideoFrameType video_frame_type) {
277 video_frame_type_ = video_frame_type;
278 RtpPacketizer::PayloadSizeLimits pay_load_size_limits;
279 // Reduce max payload length to make sure the key frame generates two
280 // packets.
281 pay_load_size_limits.max_payload_len = 8;
282 RTPVideoHeaderVP9 rtp_video_header_vp9;
283 rtp_video_header_vp9.InitRTPVideoHeaderVP9();
284 rtp_video_header_vp9.inter_pic_predicted =
285 (video_frame_type == VideoFrameType::kVideoFrameDelta);
286 rtp_packetizer_ = std::make_unique<RtpPacketizerVp9>(
287 payload, pay_load_size_limits, rtp_video_header_vp9);
288 }
289
290 size_t NumPackets() { return rtp_packetizer_->NumPackets(); }
291 void SetColorSpace(const ColorSpace& color_space) {
292 color_space_ = color_space;
293 }
294
295 RtpPacketReceived NextPacket() {
296 RtpHeaderExtensionMap extension_map;
297 extension_map.Register<ColorSpaceExtension>(1);
298 RtpPacketToSend packet_to_send(&extension_map);
299 packet_to_send.SetSequenceNumber(sequence_number_++);
300 packet_to_send.SetSsrc(kSsrc);
301 packet_to_send.SetPayloadType(kVp9PayloadType);
302 bool include_color_space =
303 (rtp_packetizer_->NumPackets() == 1u &&
304 video_frame_type_ == VideoFrameType::kVideoFrameKey);
305 if (include_color_space) {
306 EXPECT_TRUE(
307 packet_to_send.SetExtension<ColorSpaceExtension>(color_space_));
308 }
309 rtp_packetizer_->NextPacket(&packet_to_send);
310
311 RtpPacketReceived received_packet(&extension_map);
312 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
313 return received_packet;
314 }
315
316 private:
317 uint16_t sequence_number_ = 0;
318 VideoFrameType video_frame_type_;
319 ColorSpace color_space_;
320 std::unique_ptr<RtpPacketizer> rtp_packetizer_;
321 } received_packet_generator;
322 received_packet_generator.SetColorSpace(kColorSpace);
323
324 // Prepare the receiver for VP9.
Philipp Hanckede172522023-12-14 08:45:39325 webrtc::CodecParameterMap codec_params;
Danil Chapovalov5653c952021-08-10 14:57:56326 rtp_video_stream_receiver_->AddReceiveCodec(kVp9PayloadType, kVideoCodecVP9,
Niels Möller5401bad2020-08-11 10:17:42327 codec_params,
Tommid3807da2020-05-22 15:36:36328 /*raw_payload=*/false);
329
330 // Generate key frame packets.
331 received_packet_generator.SetPayload(kKeyFramePayload,
332 VideoFrameType::kVideoFrameKey);
333 EXPECT_EQ(received_packet_generator.NumPackets(), 2u);
334 RtpPacketReceived key_frame_packet1 = received_packet_generator.NextPacket();
335 RtpPacketReceived key_frame_packet2 = received_packet_generator.NextPacket();
336
337 // Generate delta frame packet.
338 received_packet_generator.SetPayload(kDeltaFramePayload,
339 VideoFrameType::kVideoFrameDelta);
340 EXPECT_EQ(received_packet_generator.NumPackets(), 1u);
341 RtpPacketReceived delta_frame_packet = received_packet_generator.NextPacket();
342
343 rtp_video_stream_receiver_->StartReceive();
344 mock_on_complete_frame_callback_.AppendExpectedBitstream(
345 kKeyFramePayload.data(), kKeyFramePayload.size());
346
347 // Send the key frame and expect a callback with color space information.
348 EXPECT_FALSE(key_frame_packet1.GetExtension<ColorSpaceExtension>());
349 EXPECT_TRUE(key_frame_packet2.GetExtension<ColorSpaceExtension>());
350 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
351 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
philipelca188092021-03-23 11:00:49352 .WillOnce(Invoke([kColorSpace](EncodedFrame* frame) {
Tommid3807da2020-05-22 15:36:36353 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
354 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
355 }));
356 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet2);
357 // Resend the first key frame packet to simulate padding for example.
358 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet1);
359
360 mock_on_complete_frame_callback_.ClearExpectedBitstream();
361 mock_on_complete_frame_callback_.AppendExpectedBitstream(
362 kDeltaFramePayload.data(), kDeltaFramePayload.size());
363
364 // Expect delta frame to have color space set even though color space not
365 // included in the RTP packet.
366 EXPECT_FALSE(delta_frame_packet.GetExtension<ColorSpaceExtension>());
367 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
philipelca188092021-03-23 11:00:49368 .WillOnce(Invoke([kColorSpace](EncodedFrame* frame) {
Tommid3807da2020-05-22 15:36:36369 ASSERT_TRUE(frame->EncodedImage().ColorSpace());
370 EXPECT_EQ(*frame->EncodedImage().ColorSpace(), kColorSpace);
371 }));
372 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
373}
374
Erik Språng5fc74892024-11-29 11:03:51375class ReceivedPacketGenerator {
376 public:
377 ReceivedPacketGenerator() = default;
378
379 void SetPayload(const std::vector<uint8_t>& payload,
380 VideoFrameType video_frame_type) {
381 video_frame_type_ = video_frame_type;
382 RtpPacketizer::PayloadSizeLimits pay_load_size_limits;
383 RTPVideoHeaderVP9 rtp_video_header_vp9;
384 rtp_video_header_vp9.InitRTPVideoHeaderVP9();
385 rtp_video_header_vp9.inter_pic_predicted =
386 (video_frame_type == VideoFrameType::kVideoFrameDelta);
387 rtp_packetizer_ = std::make_unique<RtpPacketizerVp9>(
388 payload, pay_load_size_limits, rtp_video_header_vp9);
389 }
390
391 size_t NumPackets() { return rtp_packetizer_->NumPackets(); }
392
393 void SetCorruptionDetectionHeader(const CorruptionDetectionMessage& msg) {
394 corruption_detection_msg_ = msg;
395 }
396
397 RtpPacketReceived NextPacket(bool include_corruption_header) {
398 RtpHeaderExtensionMap extension_map;
399 extension_map.Register<CorruptionDetectionExtension>(/*id=*/1);
400 RtpPacketToSend packet_to_send(&extension_map);
401 packet_to_send.SetSequenceNumber(sequence_number_++);
402 packet_to_send.SetSsrc(kSsrc);
403 packet_to_send.SetPayloadType(kVp9PayloadType);
404 packet_to_send.SetTimestamp(timestamp_++);
405 if (include_corruption_header) {
406 EXPECT_TRUE(packet_to_send.SetExtension<CorruptionDetectionExtension>(
407 corruption_detection_msg_));
408 }
409 rtp_packetizer_->NextPacket(&packet_to_send);
410
411 RtpPacketReceived received_packet(&extension_map);
412 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
413 return received_packet;
414 }
415
416 private:
417 uint16_t sequence_number_ = 0;
418 uint32_t timestamp_ = 0;
419 VideoFrameType video_frame_type_;
420 CorruptionDetectionMessage corruption_detection_msg_;
421 std::unique_ptr<RtpPacketizer> rtp_packetizer_;
422};
423
424std::optional<CorruptionDetectionMessage> GetCorruptionDetectionMessage(
425 int sequence_idx,
426 bool interpret_as_MSB) {
427 CorruptionDetectionMessage::Builder builder;
428 builder.WithSequenceIndex(sequence_idx);
429 builder.WithInterpretSequenceIndexAsMostSignificantBits(interpret_as_MSB);
430 builder.WithStdDev(kStd);
431 builder.WithLumaErrorThreshold(kLumaThreshold);
432 builder.WithChromaErrorThreshold(kChormaThreshold);
433
434 double sample_value = 0.5;
435 std::vector<double> sample_values;
436 for (int i = 0; i < kNumSamples; i++) {
437 sample_values.push_back(sample_value);
438 sample_value += 0.5;
439 }
440 builder.WithSampleValues(sample_values);
441
442 std::optional<CorruptionDetectionMessage> kCorruptionDetectionMsg =
443 builder.Build();
444 return kCorruptionDetectionMsg;
445}
446
447TEST_F(RtpVideoStreamReceiver2Test,
448 FrameInstrumentationDataGetsPopulatedLSBIncreasedCorrectly) {
449 const std::vector<uint8_t> kKeyFramePayload = {0, 1, 2, 3, 4};
450 const std::vector<uint8_t> kDeltaFramePayload = {5, 6, 7, 8, 9};
451
452 // Prepare the receiver for VP9.
453 webrtc::CodecParameterMap codec_params;
454 rtp_video_stream_receiver_->AddReceiveCodec(kVp9PayloadType, kVideoCodecVP9,
455 codec_params,
456 /*raw_payload=*/false);
457
458 ReceivedPacketGenerator received_packet_generator;
459 std::optional<CorruptionDetectionMessage> corruption_detection_msg =
460 GetCorruptionDetectionMessage(
461 /*sequence_idx=*/0, /*interpret_as_MSB*/ true);
462 ASSERT_TRUE(corruption_detection_msg.has_value());
463 received_packet_generator.SetCorruptionDetectionHeader(
464 *corruption_detection_msg);
465
466 // Generate key frame packets.
467 received_packet_generator.SetPayload(kKeyFramePayload,
468 VideoFrameType::kVideoFrameKey);
469 // Have corruption header on the key frame.
470 RtpPacketReceived key_frame_packet =
471 received_packet_generator.NextPacket(/*include_corruption_header=*/true);
472 // Generate delta frame packet.
473 received_packet_generator.SetPayload(kDeltaFramePayload,
474 VideoFrameType::kVideoFrameDelta);
475 // Don't have corruption header on the delta frame (is not a general rule).
476 RtpPacketReceived delta_frame_packet =
477 received_packet_generator.NextPacket(/*include_corruption_header=*/false);
478
479 rtp_video_stream_receiver_->StartReceive();
480 mock_on_complete_frame_callback_.AppendExpectedBitstream(
481 kKeyFramePayload.data(), kKeyFramePayload.size());
482
483 EXPECT_TRUE(key_frame_packet.GetExtension<CorruptionDetectionExtension>());
484 std::unique_ptr<EncodedFrame> key_encoded_frame;
485 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
486 .WillOnce([&](EncodedFrame* encoded_frame) {
487 key_encoded_frame = std::make_unique<EncodedFrame>(*encoded_frame);
488 });
489 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet);
490 ASSERT_TRUE(key_encoded_frame != nullptr);
491 std::optional<
492 absl::variant<FrameInstrumentationSyncData, FrameInstrumentationData>>
493 data_key_frame =
494 key_encoded_frame->CodecSpecific()->frame_instrumentation_data;
495 ASSERT_TRUE(data_key_frame.has_value());
496 ASSERT_TRUE(
497 absl::holds_alternative<FrameInstrumentationData>(*data_key_frame));
498 FrameInstrumentationData frame_inst_data_key_frame =
499 absl::get<FrameInstrumentationData>(*data_key_frame);
500 EXPECT_EQ(frame_inst_data_key_frame.sequence_index, 0);
501 EXPECT_TRUE(frame_inst_data_key_frame.communicate_upper_bits);
502 EXPECT_THAT(frame_inst_data_key_frame.std_dev, DoubleNear(kStd, 0.1));
503 EXPECT_EQ(frame_inst_data_key_frame.luma_error_threshold, kLumaThreshold);
504 EXPECT_EQ(frame_inst_data_key_frame.chroma_error_threshold, kChormaThreshold);
505
506 mock_on_complete_frame_callback_.ClearExpectedBitstream();
507 mock_on_complete_frame_callback_.AppendExpectedBitstream(
508 kDeltaFramePayload.data(), kDeltaFramePayload.size());
509
510 EXPECT_FALSE(delta_frame_packet.GetExtension<CorruptionDetectionExtension>());
511 std::unique_ptr<EncodedFrame> delta_encoded_frame;
512 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
513 .WillOnce([&](EncodedFrame* encoded_frame) {
514 delta_encoded_frame = std::make_unique<EncodedFrame>(*encoded_frame);
515 });
516 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
517 ASSERT_TRUE(delta_encoded_frame != nullptr);
518 // Not delta frame specific but as this test is designed, second frame
519 // shouldnt have corruption header.
520 EXPECT_FALSE(delta_encoded_frame->CodecSpecific()
521 ->frame_instrumentation_data.has_value());
522}
523
524TEST_F(RtpVideoStreamReceiver2Test,
525 FrameInstrumentationDataGetsPopulatedMSBIncreasedCorrectly) {
526 const std::vector<uint8_t> kKeyFramePayload = {0, 1, 2, 3, 4};
527 const std::vector<uint8_t> kDeltaFramePayload = {5, 6, 7, 8, 9};
528
529 // Prepare the receiver for VP9.
530 webrtc::CodecParameterMap codec_params;
531 rtp_video_stream_receiver_->AddReceiveCodec(kVp9PayloadType, kVideoCodecVP9,
532 codec_params,
533 /*raw_payload=*/false);
534
535 ReceivedPacketGenerator received_packet_generator;
536 std::optional<CorruptionDetectionMessage> corruption_detection_msg =
537 GetCorruptionDetectionMessage(
538 /*sequence_idx=*/0, /*interpret_as_MSB*/ true);
539 ASSERT_TRUE(corruption_detection_msg.has_value());
540 received_packet_generator.SetCorruptionDetectionHeader(
541 *corruption_detection_msg);
542
543 // Generate key frame packets.
544 received_packet_generator.SetPayload(kKeyFramePayload,
545 VideoFrameType::kVideoFrameKey);
546 // Have corruption header on the key frame.
547 RtpPacketReceived key_frame_packet =
548 received_packet_generator.NextPacket(/*include_corruption_header=*/true);
549 rtp_video_stream_receiver_->StartReceive();
550 mock_on_complete_frame_callback_.AppendExpectedBitstream(
551 kKeyFramePayload.data(), kKeyFramePayload.size());
552 rtp_video_stream_receiver_->OnRtpPacket(key_frame_packet);
553
554 RtpPacketReceived delta_frame_packet;
555 int sequence_idx = 0;
556 for (int i = 0; i < 10; i++) {
557 sequence_idx += kNumSamples;
558 if (sequence_idx > kMaxSequenceIdx) {
559 sequence_idx = sequence_idx - (kMaxSequenceIdx + 1);
560 }
561 corruption_detection_msg = GetCorruptionDetectionMessage(
562 /*sequence_idx=*/sequence_idx, /*interpret_as_MSB*/ false);
563 ASSERT_TRUE(corruption_detection_msg.has_value());
564 received_packet_generator.SetCorruptionDetectionHeader(
565 *corruption_detection_msg);
566
567 // Generate delta frame packet.
568 received_packet_generator.SetPayload(kDeltaFramePayload,
569 VideoFrameType::kVideoFrameDelta);
570 // Send corruption header with each frame.
571 delta_frame_packet = received_packet_generator.NextPacket(
572 /*include_corruption_header=*/true);
573
574 mock_on_complete_frame_callback_.ClearExpectedBitstream();
575 mock_on_complete_frame_callback_.AppendExpectedBitstream(
576 kDeltaFramePayload.data(), kDeltaFramePayload.size());
577
578 EXPECT_TRUE(
579 delta_frame_packet.GetExtension<CorruptionDetectionExtension>());
580 std::unique_ptr<EncodedFrame> delta_encoded_frame;
581 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
582 .WillOnce([&](EncodedFrame* encoded_frame) {
583 delta_encoded_frame = std::make_unique<EncodedFrame>(*encoded_frame);
584 });
585 rtp_video_stream_receiver_->OnRtpPacket(delta_frame_packet);
586 ASSERT_TRUE(delta_encoded_frame != nullptr);
587 std::optional<
588 absl::variant<FrameInstrumentationSyncData, FrameInstrumentationData>>
589 data = delta_encoded_frame->CodecSpecific()->frame_instrumentation_data;
590 ASSERT_TRUE(data.has_value());
591 ASSERT_TRUE(absl::holds_alternative<FrameInstrumentationData>(*data));
592 FrameInstrumentationData frame_inst_data =
593 absl::get<FrameInstrumentationData>(*data);
594 if (frame_inst_data.sequence_index < (kMaxSequenceIdx + 1)) {
595 EXPECT_EQ(frame_inst_data.sequence_index, sequence_idx);
596 } else {
597 EXPECT_EQ(frame_inst_data.sequence_index,
598 sequence_idx + kMaxSequenceIdx + 1);
599 }
600 }
601}
602
603// TODO: bugs.webrtc.org/358039777 - Add tests for corruption detection when we
604// have scalability.
605
Tommid3807da2020-05-22 15:36:36606TEST_F(RtpVideoStreamReceiver2Test, GenericKeyFrame) {
607 RtpPacketReceived rtp_packet;
Ali Tofigh2ab914c2022-04-13 10:55:15608 rtc::CopyOnWriteBuffer data({'1', '2', '3', '4'});
Tommid3807da2020-05-22 15:36:36609 rtp_packet.SetPayloadType(kPayloadType);
610 rtp_packet.SetSequenceNumber(1);
611 RTPVideoHeader video_header =
612 GetGenericVideoHeader(VideoFrameType::kVideoFrameKey);
613 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
614 data.size());
615 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
616 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58617 video_header, 0);
Tommid3807da2020-05-22 15:36:36618}
619
Sergey Silkin1cb3cde2022-11-01 08:56:59620TEST_F(RtpVideoStreamReceiver2Test, SetProtectionPayloadTypes) {
621 EXPECT_NE(rtp_video_stream_receiver_->red_payload_type(), 104);
622 EXPECT_NE(rtp_video_stream_receiver_->ulpfec_payload_type(), 107);
623
624 rtp_video_stream_receiver_->SetProtectionPayloadTypes(104, 107);
625
626 EXPECT_EQ(rtp_video_stream_receiver_->red_payload_type(), 104);
627 EXPECT_EQ(rtp_video_stream_receiver_->ulpfec_payload_type(), 107);
628}
629
Tommid3807da2020-05-22 15:36:36630TEST_F(RtpVideoStreamReceiver2Test, PacketInfoIsPropagatedIntoVideoFrames) {
631 constexpr uint64_t kAbsoluteCaptureTimestamp = 12;
632 constexpr int kId0 = 1;
633
634 RtpHeaderExtensionMap extension_map;
635 extension_map.Register<AbsoluteCaptureTimeExtension>(kId0);
636 RtpPacketReceived rtp_packet(&extension_map);
637 rtp_packet.SetPayloadType(kPayloadType);
Ali Tofigh2ab914c2022-04-13 10:55:15638 rtc::CopyOnWriteBuffer data({'1', '2', '3', '4'});
Tommid3807da2020-05-22 15:36:36639 rtp_packet.SetSequenceNumber(1);
640 rtp_packet.SetTimestamp(1);
641 rtp_packet.SetSsrc(kSsrc);
642 rtp_packet.SetExtension<AbsoluteCaptureTimeExtension>(
643 AbsoluteCaptureTime{kAbsoluteCaptureTimestamp,
Florent Castelli8037fc62024-08-29 13:00:40644 /*estimated_capture_clock_offset=*/std::nullopt});
Tommid3807da2020-05-22 15:36:36645
646 RTPVideoHeader video_header =
647 GetGenericVideoHeader(VideoFrameType::kVideoFrameKey);
648 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
649 data.size());
650 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
philipelca188092021-03-23 11:00:49651 .WillOnce(Invoke([kAbsoluteCaptureTimestamp](EncodedFrame* frame) {
652 EXPECT_THAT(GetAbsoluteCaptureTimestamps(frame),
653 ElementsAre(kAbsoluteCaptureTimestamp));
654 }));
Tommid3807da2020-05-22 15:36:36655 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58656 video_header, 0);
Tommid3807da2020-05-22 15:36:36657}
658
659TEST_F(RtpVideoStreamReceiver2Test,
660 MissingAbsoluteCaptureTimeIsFilledWithExtrapolatedValue) {
661 constexpr uint64_t kAbsoluteCaptureTimestamp = 12;
662 constexpr int kId0 = 1;
663
664 RtpHeaderExtensionMap extension_map;
665 extension_map.Register<AbsoluteCaptureTimeExtension>(kId0);
666 RtpPacketReceived rtp_packet(&extension_map);
667 rtp_packet.SetPayloadType(kPayloadType);
668
Ali Tofigh2ab914c2022-04-13 10:55:15669 rtc::CopyOnWriteBuffer data({'1', '2', '3', '4'});
Tommid3807da2020-05-22 15:36:36670 uint16_t sequence_number = 1;
671 uint32_t rtp_timestamp = 1;
672 rtp_packet.SetSequenceNumber(sequence_number);
673 rtp_packet.SetTimestamp(rtp_timestamp);
674 rtp_packet.SetSsrc(kSsrc);
675 rtp_packet.SetExtension<AbsoluteCaptureTimeExtension>(
676 AbsoluteCaptureTime{kAbsoluteCaptureTimestamp,
Florent Castelli8037fc62024-08-29 13:00:40677 /*estimated_capture_clock_offset=*/std::nullopt});
Tommid3807da2020-05-22 15:36:36678
679 RTPVideoHeader video_header =
680 GetGenericVideoHeader(VideoFrameType::kVideoFrameKey);
681 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
682 data.size());
683 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
684 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58685 video_header, 0);
Tommid3807da2020-05-22 15:36:36686
687 // Rtp packet without absolute capture time.
688 rtp_packet = RtpPacketReceived(&extension_map);
689 rtp_packet.SetPayloadType(kPayloadType);
690 rtp_packet.SetSequenceNumber(++sequence_number);
691 rtp_packet.SetTimestamp(++rtp_timestamp);
692 rtp_packet.SetSsrc(kSsrc);
693
694 // There is no absolute capture time in the second packet.
695 // Expect rtp video stream receiver to extrapolate it for the resulting video
696 // frame using absolute capture time from the previous packet.
697 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
philipelca188092021-03-23 11:00:49698 .WillOnce(Invoke([](EncodedFrame* frame) {
Tommid3807da2020-05-22 15:36:36699 EXPECT_THAT(GetAbsoluteCaptureTimestamps(frame), SizeIs(1));
700 }));
701 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58702 video_header, 0);
Tommid3807da2020-05-22 15:36:36703}
704
705TEST_F(RtpVideoStreamReceiver2Test,
706 NoInfiniteRecursionOnEncapsulatedRedPacket) {
707 const std::vector<uint8_t> data({
708 0x80, // RTP version.
709 kRedPayloadType, // Payload type.
710 0, 0, 0, 0, 0, 0, // Don't care.
711 0, 0, 0x4, 0x57, // SSRC
712 kRedPayloadType, // RED header.
713 0, 0, 0, 0, 0 // Don't care.
714 });
715 RtpPacketReceived packet;
716 EXPECT_TRUE(packet.Parse(data.data(), data.size()));
717 rtp_video_stream_receiver_->StartReceive();
718 rtp_video_stream_receiver_->OnRtpPacket(packet);
719}
720
721TEST_F(RtpVideoStreamReceiver2Test,
722 DropsPacketWithRedPayloadTypeAndEmptyPayload) {
723 const uint8_t kRedPayloadType = 125;
724 config_.rtp.red_payload_type = kRedPayloadType;
725 SetUp(); // re-create rtp_video_stream_receiver with red payload type.
726 // clang-format off
727 const uint8_t data[] = {
728 0x80, // RTP version.
729 kRedPayloadType, // Payload type.
730 0, 0, 0, 0, 0, 0, // Don't care.
731 0, 0, 0x4, 0x57, // SSRC
732 // Empty rtp payload.
733 };
734 // clang-format on
735 RtpPacketReceived packet;
736 // Manually convert to CopyOnWriteBuffer to be sure capacity == size
737 // and asan bot can catch read buffer overflow.
738 EXPECT_TRUE(packet.Parse(rtc::CopyOnWriteBuffer(data)));
739 rtp_video_stream_receiver_->StartReceive();
740 rtp_video_stream_receiver_->OnRtpPacket(packet);
741 // Expect asan doesn't find anything.
742}
743
744TEST_F(RtpVideoStreamReceiver2Test, GenericKeyFrameBitstreamError) {
745 RtpPacketReceived rtp_packet;
746 rtp_packet.SetPayloadType(kPayloadType);
Ali Tofigh2ab914c2022-04-13 10:55:15747 rtc::CopyOnWriteBuffer data({'1', '2', '3', '4'});
Tommid3807da2020-05-22 15:36:36748 rtp_packet.SetSequenceNumber(1);
749 RTPVideoHeader video_header =
750 GetGenericVideoHeader(VideoFrameType::kVideoFrameKey);
751 constexpr uint8_t expected_bitsteam[] = {1, 2, 3, 0xff};
752 mock_on_complete_frame_callback_.AppendExpectedBitstream(
753 expected_bitsteam, sizeof(expected_bitsteam));
754 EXPECT_CALL(mock_on_complete_frame_callback_,
755 DoOnCompleteFrameFailBitstream(_));
756 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58757 video_header, 0);
Tommid3807da2020-05-22 15:36:36758}
759
Erik Språngeb3307f2022-08-22 09:06:06760class RtpVideoStreamReceiver2TestH264
761 : public RtpVideoStreamReceiver2Test,
762 public ::testing::WithParamInterface<std::string> {
763 protected:
764 RtpVideoStreamReceiver2TestH264() : RtpVideoStreamReceiver2Test(GetParam()) {}
765};
766
Jianjun Zhu326df692024-04-15 01:11:25767INSTANTIATE_TEST_SUITE_P(SpsPpsIdrIsKeyframeAndH26xPacketBuffer,
Erik Språngeb3307f2022-08-22 09:06:06768 RtpVideoStreamReceiver2TestH264,
Jianjun Zhu326df692024-04-15 01:11:25769 Values("",
770 "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/",
771 "WebRTC-Video-H26xPacketBuffer/Enabled/",
772 "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"
773 "WebRTC-Video-H26xPacketBuffer/Enabled/"));
Erik Språngeb3307f2022-08-22 09:06:06774
775TEST_P(RtpVideoStreamReceiver2TestH264, InBandSpsPps) {
Jianjun Zhu326df692024-04-15 01:11:25776 constexpr int kH264PayloadType = 98;
777 webrtc::CodecParameterMap codec_params;
778 rtp_video_stream_receiver_->AddReceiveCodec(kH264PayloadType, kVideoCodecH264,
779 codec_params,
780 /*raw_payload=*/false);
781 rtp_video_stream_receiver_->StartReceive();
782
Tommid3807da2020-05-22 15:36:36783 rtc::CopyOnWriteBuffer sps_data;
784 RtpPacketReceived rtp_packet;
785 RTPVideoHeader sps_video_header = GetDefaultH264VideoHeader();
786 AddSps(&sps_video_header, 0, &sps_data);
787 rtp_packet.SetSequenceNumber(0);
Jianjun Zhu326df692024-04-15 01:11:25788 rtp_packet.SetPayloadType(kH264PayloadType);
Tommid3807da2020-05-22 15:36:36789 sps_video_header.is_first_packet_in_frame = true;
790 sps_video_header.frame_type = VideoFrameType::kEmptyFrame;
791 mock_on_complete_frame_callback_.AppendExpectedBitstream(
792 kH264StartCode, sizeof(kH264StartCode));
793 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
794 sps_data.size());
795 rtp_video_stream_receiver_->OnReceivedPayloadData(sps_data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58796 sps_video_header, 0);
Tommid3807da2020-05-22 15:36:36797
798 rtc::CopyOnWriteBuffer pps_data;
799 RTPVideoHeader pps_video_header = GetDefaultH264VideoHeader();
800 AddPps(&pps_video_header, 0, 1, &pps_data);
801 rtp_packet.SetSequenceNumber(1);
Jianjun Zhu326df692024-04-15 01:11:25802 rtp_packet.SetPayloadType(kH264PayloadType);
Tommid3807da2020-05-22 15:36:36803 pps_video_header.is_first_packet_in_frame = true;
804 pps_video_header.frame_type = VideoFrameType::kEmptyFrame;
805 mock_on_complete_frame_callback_.AppendExpectedBitstream(
806 kH264StartCode, sizeof(kH264StartCode));
807 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
808 pps_data.size());
809 rtp_video_stream_receiver_->OnReceivedPayloadData(pps_data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58810 pps_video_header, 0);
Tommid3807da2020-05-22 15:36:36811
812 rtc::CopyOnWriteBuffer idr_data;
813 RTPVideoHeader idr_video_header = GetDefaultH264VideoHeader();
814 AddIdr(&idr_video_header, 1);
815 rtp_packet.SetSequenceNumber(2);
Jianjun Zhu326df692024-04-15 01:11:25816 rtp_packet.SetPayloadType(kH264PayloadType);
817 rtp_packet.SetMarker(true);
Tommid3807da2020-05-22 15:36:36818 idr_video_header.is_first_packet_in_frame = true;
819 idr_video_header.is_last_packet_in_frame = true;
820 idr_video_header.frame_type = VideoFrameType::kVideoFrameKey;
821 const uint8_t idr[] = {0x65, 1, 2, 3};
822 idr_data.AppendData(idr);
823 mock_on_complete_frame_callback_.AppendExpectedBitstream(
824 kH264StartCode, sizeof(kH264StartCode));
825 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
826 idr_data.size());
827 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
828 rtp_video_stream_receiver_->OnReceivedPayloadData(idr_data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58829 idr_video_header, 0);
Tommid3807da2020-05-22 15:36:36830}
831
Erik Språngeb3307f2022-08-22 09:06:06832TEST_P(RtpVideoStreamReceiver2TestH264, OutOfBandFmtpSpsPps) {
Tommid3807da2020-05-22 15:36:36833 constexpr int kPayloadType = 99;
Philipp Hanckede172522023-12-14 08:45:39834 webrtc::CodecParameterMap codec_params;
Tommid3807da2020-05-22 15:36:36835 // Example parameter sets from https://tools.ietf.org/html/rfc3984#section-8.2
836 // .
837 codec_params.insert(
838 {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="});
Danil Chapovalov5653c952021-08-10 14:57:56839 rtp_video_stream_receiver_->AddReceiveCodec(kPayloadType, kVideoCodecH264,
840 codec_params,
Tommid3807da2020-05-22 15:36:36841 /*raw_payload=*/false);
Jianjun Zhu326df692024-04-15 01:11:25842 rtp_video_stream_receiver_->StartReceive();
Tommid3807da2020-05-22 15:36:36843 const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
844 0x53, 0x05, 0x89, 0x88};
845 mock_on_complete_frame_callback_.AppendExpectedBitstream(
846 kH264StartCode, sizeof(kH264StartCode));
847 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_sps,
848 sizeof(binary_sps));
849 const uint8_t binary_pps[] = {0x68, 0xc9, 0x63, 0x88};
850 mock_on_complete_frame_callback_.AppendExpectedBitstream(
851 kH264StartCode, sizeof(kH264StartCode));
852 mock_on_complete_frame_callback_.AppendExpectedBitstream(binary_pps,
853 sizeof(binary_pps));
854
855 RtpPacketReceived rtp_packet;
856 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
857 AddIdr(&video_header, 0);
858 rtp_packet.SetPayloadType(kPayloadType);
859 rtp_packet.SetSequenceNumber(2);
Jianjun Zhu326df692024-04-15 01:11:25860 rtp_packet.SetMarker(true);
Tommid3807da2020-05-22 15:36:36861 video_header.is_first_packet_in_frame = true;
862 video_header.is_last_packet_in_frame = true;
863 video_header.codec = kVideoCodecH264;
864 video_header.frame_type = VideoFrameType::kVideoFrameKey;
Ali Tofigh2ab914c2022-04-13 10:55:15865 rtc::CopyOnWriteBuffer data({'1', '2', '3'});
Tommid3807da2020-05-22 15:36:36866 mock_on_complete_frame_callback_.AppendExpectedBitstream(
867 kH264StartCode, sizeof(kH264StartCode));
868 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
869 data.size());
Jianjun Zhu326df692024-04-15 01:11:25870 // IDR frames without SPS/PPS are not returned by
871 // |H26xPacketBuffer.InsertPacket| until SPS and PPS are received when
872 // WebRTC-SpsPpsIdrIsH264Keyframe is enabled.
Danil Chapovalove2fee232024-08-29 09:50:33873 if (!env_.field_trials().IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe") ||
874 !env_.field_trials().IsEnabled("WebRTC-Video-H26xPacketBuffer")) {
Jianjun Zhu326df692024-04-15 01:11:25875 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
876 }
Tommid3807da2020-05-22 15:36:36877 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58878 video_header, 0);
Tommid3807da2020-05-22 15:36:36879}
880
Erik Språngeb3307f2022-08-22 09:06:06881TEST_P(RtpVideoStreamReceiver2TestH264, ForceSpsPpsIdrIsKeyframe) {
Andrew Johnsonf288f5b2020-09-19 05:35:59882 constexpr int kPayloadType = 99;
Philipp Hanckede172522023-12-14 08:45:39883 webrtc::CodecParameterMap codec_params;
Jianjun Zhu326df692024-04-15 01:11:25884 // Forcing can be done either with field trial or codec_params.
Danil Chapovalove2fee232024-08-29 09:50:33885 if (!env_.field_trials().IsEnabled("WebRTC-SpsPpsIdrIsH264Keyframe")) {
Erik Språngeb3307f2022-08-22 09:06:06886 codec_params.insert({cricket::kH264FmtpSpsPpsIdrInKeyframe, ""});
887 }
Danil Chapovalov5653c952021-08-10 14:57:56888 rtp_video_stream_receiver_->AddReceiveCodec(kPayloadType, kVideoCodecH264,
889 codec_params,
Andrew Johnsonf288f5b2020-09-19 05:35:59890 /*raw_payload=*/false);
Jianjun Zhu326df692024-04-15 01:11:25891 rtp_video_stream_receiver_->StartReceive();
Andrew Johnsonf288f5b2020-09-19 05:35:59892 rtc::CopyOnWriteBuffer sps_data;
893 RtpPacketReceived rtp_packet;
894 RTPVideoHeader sps_video_header = GetDefaultH264VideoHeader();
895 AddSps(&sps_video_header, 0, &sps_data);
896 rtp_packet.SetSequenceNumber(0);
897 rtp_packet.SetPayloadType(kPayloadType);
898 sps_video_header.is_first_packet_in_frame = true;
899 sps_video_header.frame_type = VideoFrameType::kEmptyFrame;
900 mock_on_complete_frame_callback_.AppendExpectedBitstream(
901 kH264StartCode, sizeof(kH264StartCode));
902 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps_data.data(),
903 sps_data.size());
904 rtp_video_stream_receiver_->OnReceivedPayloadData(sps_data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58905 sps_video_header, 0);
Andrew Johnsonf288f5b2020-09-19 05:35:59906
907 rtc::CopyOnWriteBuffer pps_data;
908 RTPVideoHeader pps_video_header = GetDefaultH264VideoHeader();
909 AddPps(&pps_video_header, 0, 1, &pps_data);
910 rtp_packet.SetSequenceNumber(1);
911 pps_video_header.is_first_packet_in_frame = true;
912 pps_video_header.frame_type = VideoFrameType::kEmptyFrame;
913 mock_on_complete_frame_callback_.AppendExpectedBitstream(
914 kH264StartCode, sizeof(kH264StartCode));
915 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps_data.data(),
916 pps_data.size());
917 rtp_video_stream_receiver_->OnReceivedPayloadData(pps_data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58918 pps_video_header, 0);
Andrew Johnsonf288f5b2020-09-19 05:35:59919
920 rtc::CopyOnWriteBuffer idr_data;
921 RTPVideoHeader idr_video_header = GetDefaultH264VideoHeader();
922 AddIdr(&idr_video_header, 1);
923 rtp_packet.SetSequenceNumber(2);
Jianjun Zhu326df692024-04-15 01:11:25924 rtp_packet.SetMarker(true);
Andrew Johnsonf288f5b2020-09-19 05:35:59925 idr_video_header.is_first_packet_in_frame = true;
926 idr_video_header.is_last_packet_in_frame = true;
927 idr_video_header.frame_type = VideoFrameType::kVideoFrameKey;
928 const uint8_t idr[] = {0x65, 1, 2, 3};
929 idr_data.AppendData(idr);
930 mock_on_complete_frame_callback_.AppendExpectedBitstream(
931 kH264StartCode, sizeof(kH264StartCode));
932 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
933 idr_data.size());
934 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:49935 .WillOnce(
936 [&](EncodedFrame* frame) { EXPECT_TRUE(frame->is_keyframe()); });
Andrew Johnsonf288f5b2020-09-19 05:35:59937 rtp_video_stream_receiver_->OnReceivedPayloadData(idr_data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58938 idr_video_header, 0);
Andrew Johnsonf288f5b2020-09-19 05:35:59939 mock_on_complete_frame_callback_.ClearExpectedBitstream();
940 mock_on_complete_frame_callback_.AppendExpectedBitstream(
941 kH264StartCode, sizeof(kH264StartCode));
942 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr_data.data(),
943 idr_data.size());
944 rtp_packet.SetSequenceNumber(3);
Jianjun Zhu326df692024-04-15 01:11:25945 // IDR frames without SPS/PPS are not returned by
946 // |H26xPacketBuffer.InsertPacket| until SPS and PPS are received, while
947 // |PacketBuffer| returns it as a delta frame.
Danil Chapovalove2fee232024-08-29 09:50:33948 if (env_.field_trials().IsEnabled("WebRTC-Video-H26xPacketBuffer")) {
Jianjun Zhu326df692024-04-15 01:11:25949 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
950 } else {
951 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
952 .WillOnce(
953 [&](EncodedFrame* frame) { EXPECT_FALSE(frame->is_keyframe()); });
954 }
Andrew Johnsonf288f5b2020-09-19 05:35:59955 rtp_video_stream_receiver_->OnReceivedPayloadData(idr_data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58956 idr_video_header, 0);
Andrew Johnsonf288f5b2020-09-19 05:35:59957}
958
Shunbo Li6f866342024-12-17 03:39:55959class RtpVideoStreamReceiver2TestPadding
960 : public RtpVideoStreamReceiver2Test,
961 public ::testing::WithParamInterface<std::string> {
962 protected:
963 RtpVideoStreamReceiver2TestPadding()
964 : RtpVideoStreamReceiver2Test(GetParam()) {}
965};
966
967INSTANTIATE_TEST_SUITE_P(PaddingInMediaStreamAndH26xPacketBuffer,
968 RtpVideoStreamReceiver2TestPadding,
969 Values("", "WebRTC-Video-H26xPacketBuffer/Enabled/"));
970
971TEST_P(RtpVideoStreamReceiver2TestPadding, PaddingInMediaStream) {
Tommid3807da2020-05-22 15:36:36972 RtpPacketReceived rtp_packet;
973 RTPVideoHeader video_header = GetDefaultH264VideoHeader();
Ali Tofigh2ab914c2022-04-13 10:55:15974 rtc::CopyOnWriteBuffer data({'1', '2', '3'});
Tommid3807da2020-05-22 15:36:36975 rtp_packet.SetPayloadType(kPayloadType);
976 rtp_packet.SetSequenceNumber(2);
977 video_header.is_first_packet_in_frame = true;
978 video_header.is_last_packet_in_frame = true;
979 video_header.codec = kVideoCodecGeneric;
980 video_header.frame_type = VideoFrameType::kVideoFrameKey;
981 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
982 data.size());
983
984 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
985 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58986 video_header, 0);
Tommid3807da2020-05-22 15:36:36987
988 rtp_packet.SetSequenceNumber(3);
989 rtp_video_stream_receiver_->OnReceivedPayloadData({}, rtp_packet,
philipel7aff4d12024-01-17 18:26:58990 video_header, 0);
Tommid3807da2020-05-22 15:36:36991
992 rtp_packet.SetSequenceNumber(4);
993 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
994 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
995 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:58996 video_header, 0);
Tommid3807da2020-05-22 15:36:36997
998 rtp_packet.SetSequenceNumber(6);
999 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:581000 video_header, 0);
Tommid3807da2020-05-22 15:36:361001
1002 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
1003 rtp_packet.SetSequenceNumber(5);
1004 rtp_video_stream_receiver_->OnReceivedPayloadData({}, rtp_packet,
philipel7aff4d12024-01-17 18:26:581005 video_header, 0);
Tommid3807da2020-05-22 15:36:361006}
1007
Shunbo Li6f866342024-12-17 03:39:551008TEST_P(RtpVideoStreamReceiver2TestPadding, EmptyPaddingInMediaStream) {
1009 constexpr int kH264PayloadType = 98;
1010 RtpPacketReceived rtp_packet_idr, rtp_packet_padding, rtp_packet_slice;
1011 // Example Stap-A packet with SPS, PPS, and IDR.
1012 std::vector<uint8_t> raw_rtp_with_sps_pps_idr{
1013 0x80, 0xe2, 0x13, 0xba, 0x87, 0xa0, 0x0a, 0x8a, 0x00, 0x00, 0x6f,
1014 0x00, 0x78, 0x00, 0x19, 0x67, 0x42, 0x40, 0x29, 0x95, 0xb8, 0x78,
1015 0x2f, 0xf9, 0x70, 0x11, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00,
1016 0x03, 0x00, 0x78, 0x8d, 0xa1, 0xc3, 0x2e, 0x00, 0x04, 0x68, 0xce,
1017 0x3c, 0x80, 0x00, 0x07, 0x05, 0x88, 0x80, 0x03, 0x53, 0xff, 0xff};
1018 // Example Empty padding packet next Idr.
1019 std::vector<uint8_t> raw_rtp_empty_padding{
1020 0x80, 0x62, 0x13, 0xbb, 0x87, 0xa0, 0x21, 0x0a, 0x00, 0x00, 0x6f, 0x00};
1021 // Example Single NALU packet with slice.
1022 std::vector<uint8_t> raw_rtp_slice(
1023 {0x80, 0xE2, 0x13, 0xbc, 0x87, 0xa0, 0x21, 0x0a, 0x00, 0x00, 0x6f,
1024 0x00, 0x01, 0x9a, 0x02, 0x3f, 0xc1, 0x48, 0x9a, 0xeb, 0xea, 0xff});
1025
1026 // Example EncodedFrame with SPS, PPS, and IDR.
1027 std::vector<uint8_t> expect_frame_with_sps_pps_idr{
1028 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x40, 0x29, 0x95, 0xb8, 0x78, 0x2f,
1029 0xf9, 0x70, 0x11, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00,
1030 0x78, 0x8d, 0xa1, 0xc3, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x3c,
1031 0x80, 0x00, 0x00, 0x00, 0x01, 0x05, 0x88, 0x80, 0x03, 0x53, 0xff, 0xff};
1032 // Example EncodedFrame with slice.
1033 std::vector<uint8_t> expect_frame_with_slice{0x00, 0x00, 0x00, 0x01, 0x01,
1034 0x9a, 0x02, 0x3f, 0xc1, 0x48,
1035 0x9a, 0xeb, 0xea, 0xff};
1036 rtp_packet_idr.Parse(raw_rtp_with_sps_pps_idr.data(),
1037 raw_rtp_with_sps_pps_idr.size());
1038 rtp_packet_padding.Parse(raw_rtp_empty_padding.data(),
1039 raw_rtp_empty_padding.size());
1040 rtp_packet_slice.Parse(raw_rtp_slice.data(), raw_rtp_slice.size());
1041
1042 // Prepare the receiver for H264.
1043 webrtc::CodecParameterMap codec_params;
1044 rtp_video_stream_receiver_->AddReceiveCodec(kH264PayloadType, kVideoCodecH264,
1045 codec_params, false);
1046 rtp_video_stream_receiver_->StartReceive();
1047
1048 // Expect IDR frame.
1049 mock_on_complete_frame_callback_.AppendExpectedBitstream(
1050 expect_frame_with_sps_pps_idr.data(),
1051 expect_frame_with_sps_pps_idr.size());
1052 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
1053
1054 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet_idr);
1055
1056 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet_padding);
1057
1058 // Expect single NALU frame.
1059 mock_on_complete_frame_callback_.ClearExpectedBitstream();
1060 mock_on_complete_frame_callback_.AppendExpectedBitstream(
1061 expect_frame_with_slice.data(), expect_frame_with_slice.size());
1062 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
1063 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet_slice);
1064}
1065
Tommid3807da2020-05-22 15:36:361066TEST_F(RtpVideoStreamReceiver2Test, RequestKeyframeIfFirstFrameIsDelta) {
1067 RtpPacketReceived rtp_packet;
1068 rtp_packet.SetPayloadType(kPayloadType);
Ali Tofigh2ab914c2022-04-13 10:55:151069 rtc::CopyOnWriteBuffer data({'1', '2', '3', '4'});
Tommid3807da2020-05-22 15:36:361070 rtp_packet.SetSequenceNumber(1);
1071 RTPVideoHeader video_header =
1072 GetGenericVideoHeader(VideoFrameType::kVideoFrameDelta);
philipel27b35a72022-07-05 07:59:551073
Tommid3807da2020-05-22 15:36:361074 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:581075 video_header, 0);
philipel27b35a72022-07-05 07:59:551076 EXPECT_THAT(rtcp_packet_parser_.pli()->num_packets(), Eq(1));
Tommid3807da2020-05-22 15:36:361077}
1078
1079TEST_F(RtpVideoStreamReceiver2Test, RequestKeyframeWhenPacketBufferGetsFull) {
1080 constexpr int kPacketBufferMaxSize = 2048;
1081
1082 RtpPacketReceived rtp_packet;
1083 rtp_packet.SetPayloadType(kPayloadType);
Ali Tofigh2ab914c2022-04-13 10:55:151084 rtc::CopyOnWriteBuffer data({'1', '2', '3', '4'});
Tommid3807da2020-05-22 15:36:361085 RTPVideoHeader video_header =
1086 GetGenericVideoHeader(VideoFrameType::kVideoFrameDelta);
1087 // Incomplete frames so that the packet buffer is filling up.
1088 video_header.is_last_packet_in_frame = false;
1089 uint16_t start_sequence_number = 1234;
1090 rtp_packet.SetSequenceNumber(start_sequence_number);
1091 while (rtp_packet.SequenceNumber() - start_sequence_number <
1092 kPacketBufferMaxSize) {
1093 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:581094 video_header, 0);
Tommid3807da2020-05-22 15:36:361095 rtp_packet.SetSequenceNumber(rtp_packet.SequenceNumber() + 2);
1096 }
1097
Tommid3807da2020-05-22 15:36:361098 rtp_video_stream_receiver_->OnReceivedPayloadData(data, rtp_packet,
philipel7aff4d12024-01-17 18:26:581099 video_header, 0);
philipel27b35a72022-07-05 07:59:551100 EXPECT_THAT(rtcp_packet_parser_.pli()->num_packets(), Eq(1));
Tommid3807da2020-05-22 15:36:361101}
1102
Tomas Gunnarsson8408c992021-02-14 13:19:121103TEST_F(RtpVideoStreamReceiver2Test, SinkGetsRtpNotifications) {
Tommid3807da2020-05-22 15:36:361104 rtp_video_stream_receiver_->StartReceive();
1105
Tomas Gunnarsson8408c992021-02-14 13:19:121106 MockRtpPacketSink test_sink;
1107 test_packet_sink_ = &test_sink;
Tommid3807da2020-05-22 15:36:361108
1109 auto rtp_packet = CreateRtpPacketReceived();
Tomas Gunnarsson8408c992021-02-14 13:19:121110 EXPECT_CALL(test_sink, OnRtpPacket(SamePacketAs(*rtp_packet)));
Tommid3807da2020-05-22 15:36:361111
1112 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
1113
1114 // Test tear-down.
1115 rtp_video_stream_receiver_->StopReceive();
Tomas Gunnarsson8408c992021-02-14 13:19:121116 test_packet_sink_ = nullptr;
Tommid3807da2020-05-22 15:36:361117}
1118
Tomas Gunnarsson8408c992021-02-14 13:19:121119TEST_F(RtpVideoStreamReceiver2Test, NonStartedStreamGetsNoRtpCallbacks) {
Artem Titovab30d722021-07-27 14:22:111120 // Explicitly showing that the stream is not in the `started` state,
1121 // regardless of whether streams start out `started` or `stopped`.
Tommid3807da2020-05-22 15:36:361122 rtp_video_stream_receiver_->StopReceive();
1123
Tomas Gunnarsson8408c992021-02-14 13:19:121124 MockRtpPacketSink test_sink;
1125 test_packet_sink_ = &test_sink;
Tommid3807da2020-05-22 15:36:361126
1127 auto rtp_packet = CreateRtpPacketReceived();
Tomas Gunnarsson8408c992021-02-14 13:19:121128 EXPECT_CALL(test_sink, OnRtpPacket(_)).Times(0);
Tommid3807da2020-05-22 15:36:361129
1130 rtp_video_stream_receiver_->OnRtpPacket(*rtp_packet);
1131
Tomas Gunnarsson8408c992021-02-14 13:19:121132 test_packet_sink_ = nullptr;
Tommid3807da2020-05-22 15:36:361133}
1134
1135TEST_F(RtpVideoStreamReceiver2Test, ParseGenericDescriptorOnePacket) {
1136 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
1137 const int kSpatialIndex = 1;
1138
1139 rtp_video_stream_receiver_->StartReceive();
1140
1141 RtpHeaderExtensionMap extension_map;
1142 extension_map.Register<RtpGenericFrameDescriptorExtension00>(5);
1143 RtpPacketReceived rtp_packet(&extension_map);
1144 rtp_packet.SetPayloadType(kPayloadType);
1145
1146 RtpGenericFrameDescriptor generic_descriptor;
1147 generic_descriptor.SetFirstPacketInSubFrame(true);
1148 generic_descriptor.SetLastPacketInSubFrame(true);
1149 generic_descriptor.SetFrameId(100);
1150 generic_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
1151 generic_descriptor.AddFrameDependencyDiff(90);
1152 generic_descriptor.AddFrameDependencyDiff(80);
1153 ASSERT_TRUE(rtp_packet.SetExtension<RtpGenericFrameDescriptorExtension00>(
1154 generic_descriptor));
1155
1156 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
1157 memcpy(payload, data.data(), data.size());
Artem Titovab30d722021-07-27 14:22:111158 // The first byte is the header, so we ignore the first byte of `data`.
Tommid3807da2020-05-22 15:36:361159 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
1160 data.size() - 1);
1161
1162 rtp_packet.SetMarker(true);
1163 rtp_packet.SetPayloadType(kPayloadType);
1164 rtp_packet.SetSequenceNumber(1);
1165
1166 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:491167 .WillOnce(Invoke([kSpatialIndex](EncodedFrame* frame) {
Tommid3807da2020-05-22 15:36:361168 EXPECT_EQ(frame->num_references, 2U);
philipel9aa9b8d2021-02-15 12:31:291169 EXPECT_EQ(frame->references[0], frame->Id() - 90);
1170 EXPECT_EQ(frame->references[1], frame->Id() - 80);
philipela65d7852020-11-20 16:49:241171 EXPECT_EQ(frame->SpatialIndex(), kSpatialIndex);
Tommid3807da2020-05-22 15:36:361172 EXPECT_THAT(frame->PacketInfos(), SizeIs(1));
1173 }));
1174
1175 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
1176}
1177
1178TEST_F(RtpVideoStreamReceiver2Test, ParseGenericDescriptorTwoPackets) {
1179 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
1180 const int kSpatialIndex = 1;
1181
1182 rtp_video_stream_receiver_->StartReceive();
1183
1184 RtpHeaderExtensionMap extension_map;
1185 extension_map.Register<RtpGenericFrameDescriptorExtension00>(5);
1186 RtpPacketReceived first_packet(&extension_map);
1187
1188 RtpGenericFrameDescriptor first_packet_descriptor;
1189 first_packet_descriptor.SetFirstPacketInSubFrame(true);
1190 first_packet_descriptor.SetLastPacketInSubFrame(false);
1191 first_packet_descriptor.SetFrameId(100);
1192 first_packet_descriptor.SetSpatialLayersBitmask(1 << kSpatialIndex);
1193 first_packet_descriptor.SetResolution(480, 360);
1194 ASSERT_TRUE(first_packet.SetExtension<RtpGenericFrameDescriptorExtension00>(
1195 first_packet_descriptor));
1196
1197 uint8_t* first_packet_payload = first_packet.SetPayloadSize(data.size());
1198 memcpy(first_packet_payload, data.data(), data.size());
Artem Titovab30d722021-07-27 14:22:111199 // The first byte is the header, so we ignore the first byte of `data`.
Tommid3807da2020-05-22 15:36:361200 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
1201 data.size() - 1);
1202
1203 first_packet.SetPayloadType(kPayloadType);
1204 first_packet.SetSequenceNumber(1);
1205 rtp_video_stream_receiver_->OnRtpPacket(first_packet);
1206
1207 RtpPacketReceived second_packet(&extension_map);
1208 RtpGenericFrameDescriptor second_packet_descriptor;
1209 second_packet_descriptor.SetFirstPacketInSubFrame(false);
1210 second_packet_descriptor.SetLastPacketInSubFrame(true);
1211 ASSERT_TRUE(second_packet.SetExtension<RtpGenericFrameDescriptorExtension00>(
1212 second_packet_descriptor));
1213
1214 second_packet.SetMarker(true);
1215 second_packet.SetPayloadType(kPayloadType);
1216 second_packet.SetSequenceNumber(2);
1217
1218 uint8_t* second_packet_payload = second_packet.SetPayloadSize(data.size());
1219 memcpy(second_packet_payload, data.data(), data.size());
Artem Titovab30d722021-07-27 14:22:111220 // The first byte is the header, so we ignore the first byte of `data`.
Tommid3807da2020-05-22 15:36:361221 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data() + 1,
1222 data.size() - 1);
1223
1224 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:491225 .WillOnce(Invoke([kSpatialIndex](EncodedFrame* frame) {
Tommid3807da2020-05-22 15:36:361226 EXPECT_EQ(frame->num_references, 0U);
philipela65d7852020-11-20 16:49:241227 EXPECT_EQ(frame->SpatialIndex(), kSpatialIndex);
Tommid3807da2020-05-22 15:36:361228 EXPECT_EQ(frame->EncodedImage()._encodedWidth, 480u);
1229 EXPECT_EQ(frame->EncodedImage()._encodedHeight, 360u);
1230 EXPECT_THAT(frame->PacketInfos(), SizeIs(2));
1231 }));
1232
1233 rtp_video_stream_receiver_->OnRtpPacket(second_packet);
1234}
1235
1236TEST_F(RtpVideoStreamReceiver2Test, ParseGenericDescriptorRawPayload) {
1237 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
1238 const int kRawPayloadType = 123;
1239
Danil Chapovalov5653c952021-08-10 14:57:561240 rtp_video_stream_receiver_->AddReceiveCodec(kRawPayloadType,
1241 kVideoCodecGeneric, {},
Niels Möller5401bad2020-08-11 10:17:421242 /*raw_payload=*/true);
Tommid3807da2020-05-22 15:36:361243 rtp_video_stream_receiver_->StartReceive();
1244
1245 RtpHeaderExtensionMap extension_map;
1246 extension_map.Register<RtpGenericFrameDescriptorExtension00>(5);
1247 RtpPacketReceived rtp_packet(&extension_map);
1248
1249 RtpGenericFrameDescriptor generic_descriptor;
1250 generic_descriptor.SetFirstPacketInSubFrame(true);
1251 generic_descriptor.SetLastPacketInSubFrame(true);
1252 ASSERT_TRUE(rtp_packet.SetExtension<RtpGenericFrameDescriptorExtension00>(
1253 generic_descriptor));
1254
1255 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
1256 memcpy(payload, data.data(), data.size());
1257 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
1258 data.size());
1259
1260 rtp_packet.SetMarker(true);
1261 rtp_packet.SetPayloadType(kRawPayloadType);
1262 rtp_packet.SetSequenceNumber(1);
1263
1264 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
1265 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
1266}
1267
1268TEST_F(RtpVideoStreamReceiver2Test, UnwrapsFrameId) {
1269 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
1270 const int kPayloadType = 123;
1271
Danil Chapovalov5653c952021-08-10 14:57:561272 rtp_video_stream_receiver_->AddReceiveCodec(kPayloadType, kVideoCodecGeneric,
1273 {},
Niels Möller5401bad2020-08-11 10:17:421274 /*raw_payload=*/true);
Tommid3807da2020-05-22 15:36:361275 rtp_video_stream_receiver_->StartReceive();
1276 RtpHeaderExtensionMap extension_map;
1277 extension_map.Register<RtpGenericFrameDescriptorExtension00>(5);
1278
1279 uint16_t rtp_sequence_number = 1;
1280 auto inject_packet = [&](uint16_t wrapped_frame_id) {
1281 RtpPacketReceived rtp_packet(&extension_map);
1282
1283 RtpGenericFrameDescriptor generic_descriptor;
1284 generic_descriptor.SetFirstPacketInSubFrame(true);
1285 generic_descriptor.SetLastPacketInSubFrame(true);
1286 generic_descriptor.SetFrameId(wrapped_frame_id);
1287 ASSERT_TRUE(rtp_packet.SetExtension<RtpGenericFrameDescriptorExtension00>(
1288 generic_descriptor));
1289
1290 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
1291 ASSERT_TRUE(payload);
1292 memcpy(payload, data.data(), data.size());
1293 mock_on_complete_frame_callback_.ClearExpectedBitstream();
1294 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
1295 data.size());
1296 rtp_packet.SetMarker(true);
1297 rtp_packet.SetPayloadType(kPayloadType);
1298 rtp_packet.SetSequenceNumber(++rtp_sequence_number);
1299 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
1300 };
1301
1302 int64_t first_picture_id;
1303 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:491304 .WillOnce([&](EncodedFrame* frame) { first_picture_id = frame->Id(); });
Tommid3807da2020-05-22 15:36:361305 inject_packet(/*wrapped_frame_id=*/0xffff);
1306
1307 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:491308 .WillOnce([&](EncodedFrame* frame) {
philipel9aa9b8d2021-02-15 12:31:291309 EXPECT_EQ(frame->Id() - first_picture_id, 3);
Tommid3807da2020-05-22 15:36:361310 });
1311 inject_packet(/*wrapped_frame_id=*/0x0002);
1312}
1313
1314class RtpVideoStreamReceiver2DependencyDescriptorTest
1315 : public RtpVideoStreamReceiver2Test {
1316 public:
1317 RtpVideoStreamReceiver2DependencyDescriptorTest() {
Danil Chapovalov5653c952021-08-10 14:57:561318 rtp_video_stream_receiver_->AddReceiveCodec(payload_type_,
1319 kVideoCodecGeneric, {},
Tommid3807da2020-05-22 15:36:361320 /*raw_payload=*/true);
1321 extension_map_.Register<RtpDependencyDescriptorExtension>(7);
1322 rtp_video_stream_receiver_->StartReceive();
1323 }
1324
1325 // Returns some valid structure for the DependencyDescriptors.
1326 // First template of that structure always fit for a key frame.
1327 static FrameDependencyStructure CreateStreamStructure() {
1328 FrameDependencyStructure stream_structure;
1329 stream_structure.num_decode_targets = 1;
1330 stream_structure.templates = {
Danil Chapovalov24263f42020-06-11 11:23:451331 FrameDependencyTemplate().Dtis("S"),
1332 FrameDependencyTemplate().Dtis("S").FrameDiffs({1}),
Tommid3807da2020-05-22 15:36:361333 };
1334 return stream_structure;
1335 }
1336
1337 void InjectPacketWith(const FrameDependencyStructure& stream_structure,
1338 const DependencyDescriptor& dependency_descriptor) {
1339 const std::vector<uint8_t> data = {0, 1, 2, 3, 4};
1340 RtpPacketReceived rtp_packet(&extension_map_);
1341 ASSERT_TRUE(rtp_packet.SetExtension<RtpDependencyDescriptorExtension>(
1342 stream_structure, dependency_descriptor));
1343 uint8_t* payload = rtp_packet.SetPayloadSize(data.size());
1344 ASSERT_TRUE(payload);
1345 memcpy(payload, data.data(), data.size());
1346 mock_on_complete_frame_callback_.ClearExpectedBitstream();
1347 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
1348 data.size());
1349 rtp_packet.SetMarker(true);
1350 rtp_packet.SetPayloadType(payload_type_);
1351 rtp_packet.SetSequenceNumber(++rtp_sequence_number_);
1352 rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
1353 }
1354
1355 private:
1356 const int payload_type_ = 123;
1357 RtpHeaderExtensionMap extension_map_;
1358 uint16_t rtp_sequence_number_ = 321;
1359};
1360
1361TEST_F(RtpVideoStreamReceiver2DependencyDescriptorTest, UnwrapsFrameId) {
1362 FrameDependencyStructure stream_structure = CreateStreamStructure();
1363
1364 DependencyDescriptor keyframe_descriptor;
1365 keyframe_descriptor.attached_structure =
1366 std::make_unique<FrameDependencyStructure>(stream_structure);
1367 keyframe_descriptor.frame_dependencies = stream_structure.templates[0];
1368 keyframe_descriptor.frame_number = 0xfff0;
1369 // DependencyDescriptor doesn't support reordering delta frame before
1370 // keyframe. Thus feed a key frame first, then test reodered delta frames.
1371 int64_t first_picture_id;
1372 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:491373 .WillOnce([&](EncodedFrame* frame) { first_picture_id = frame->Id(); });
Tommid3807da2020-05-22 15:36:361374 InjectPacketWith(stream_structure, keyframe_descriptor);
1375
1376 DependencyDescriptor deltaframe1_descriptor;
1377 deltaframe1_descriptor.frame_dependencies = stream_structure.templates[1];
1378 deltaframe1_descriptor.frame_number = 0xfffe;
1379
1380 DependencyDescriptor deltaframe2_descriptor;
Danil Chapovalov3e989192024-12-13 13:07:541381 deltaframe2_descriptor.frame_dependencies = stream_structure.templates[1];
Tommid3807da2020-05-22 15:36:361382 deltaframe2_descriptor.frame_number = 0x0002;
1383
1384 // Parser should unwrap frame ids correctly even if packets were reordered by
1385 // the network.
1386 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:491387 .WillOnce([&](EncodedFrame* frame) {
Tommid3807da2020-05-22 15:36:361388 // 0x0002 - 0xfff0
philipel9aa9b8d2021-02-15 12:31:291389 EXPECT_EQ(frame->Id() - first_picture_id, 18);
Tommid3807da2020-05-22 15:36:361390 })
philipelca188092021-03-23 11:00:491391 .WillOnce([&](EncodedFrame* frame) {
Tommid3807da2020-05-22 15:36:361392 // 0xfffe - 0xfff0
philipel9aa9b8d2021-02-15 12:31:291393 EXPECT_EQ(frame->Id() - first_picture_id, 14);
Tommid3807da2020-05-22 15:36:361394 });
1395 InjectPacketWith(stream_structure, deltaframe2_descriptor);
1396 InjectPacketWith(stream_structure, deltaframe1_descriptor);
1397}
1398
1399TEST_F(RtpVideoStreamReceiver2DependencyDescriptorTest,
1400 DropsLateDeltaFramePacketWithDependencyDescriptorExtension) {
1401 FrameDependencyStructure stream_structure1 = CreateStreamStructure();
1402 FrameDependencyStructure stream_structure2 = CreateStreamStructure();
1403 // Make sure template ids for these two structures do not collide:
1404 // adjust structure_id (that is also used as template id offset).
1405 stream_structure1.structure_id = 13;
1406 stream_structure2.structure_id =
1407 stream_structure1.structure_id + stream_structure1.templates.size();
1408
1409 DependencyDescriptor keyframe1_descriptor;
1410 keyframe1_descriptor.attached_structure =
1411 std::make_unique<FrameDependencyStructure>(stream_structure1);
1412 keyframe1_descriptor.frame_dependencies = stream_structure1.templates[0];
1413 keyframe1_descriptor.frame_number = 1;
1414 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
1415 InjectPacketWith(stream_structure1, keyframe1_descriptor);
1416
1417 // Pass in 2nd key frame with different structure.
1418 DependencyDescriptor keyframe2_descriptor;
1419 keyframe2_descriptor.attached_structure =
1420 std::make_unique<FrameDependencyStructure>(stream_structure2);
1421 keyframe2_descriptor.frame_dependencies = stream_structure2.templates[0];
1422 keyframe2_descriptor.frame_number = 3;
1423 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame);
1424 InjectPacketWith(stream_structure2, keyframe2_descriptor);
1425
1426 // Pass in late delta frame that uses structure of the 1st key frame.
1427 DependencyDescriptor deltaframe_descriptor;
1428 deltaframe_descriptor.frame_dependencies = stream_structure1.templates[0];
1429 deltaframe_descriptor.frame_number = 2;
1430 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame).Times(0);
1431 InjectPacketWith(stream_structure1, deltaframe_descriptor);
1432}
1433
1434TEST_F(RtpVideoStreamReceiver2DependencyDescriptorTest,
1435 DropsLateKeyFramePacketWithDependencyDescriptorExtension) {
1436 FrameDependencyStructure stream_structure1 = CreateStreamStructure();
1437 FrameDependencyStructure stream_structure2 = CreateStreamStructure();
1438 // Make sure template ids for these two structures do not collide:
1439 // adjust structure_id (that is also used as template id offset).
1440 stream_structure1.structure_id = 13;
1441 stream_structure2.structure_id =
1442 stream_structure1.structure_id + stream_structure1.templates.size();
1443
1444 DependencyDescriptor keyframe1_descriptor;
1445 keyframe1_descriptor.attached_structure =
1446 std::make_unique<FrameDependencyStructure>(stream_structure1);
1447 keyframe1_descriptor.frame_dependencies = stream_structure1.templates[0];
1448 keyframe1_descriptor.frame_number = 1;
1449
1450 DependencyDescriptor keyframe2_descriptor;
1451 keyframe2_descriptor.attached_structure =
1452 std::make_unique<FrameDependencyStructure>(stream_structure2);
1453 keyframe2_descriptor.frame_dependencies = stream_structure2.templates[0];
1454 keyframe2_descriptor.frame_number = 3;
1455
1456 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:491457 .WillOnce(
1458 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 3); });
Tommid3807da2020-05-22 15:36:361459 InjectPacketWith(stream_structure2, keyframe2_descriptor);
1460 InjectPacketWith(stream_structure1, keyframe1_descriptor);
1461
1462 // Pass in delta frame that uses structure of the 2nd key frame. Late key
1463 // frame shouldn't block it.
1464 DependencyDescriptor deltaframe_descriptor;
1465 deltaframe_descriptor.frame_dependencies = stream_structure2.templates[0];
1466 deltaframe_descriptor.frame_number = 4;
1467 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
philipelca188092021-03-23 11:00:491468 .WillOnce(
1469 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 4); });
Tommid3807da2020-05-22 15:36:361470 InjectPacketWith(stream_structure2, deltaframe_descriptor);
1471}
1472
philipel17093412022-06-13 11:14:431473TEST_F(RtpVideoStreamReceiver2DependencyDescriptorTest,
1474 RequestKeyframeIfInitialKeyframePacketIsLost) {
1475 FrameDependencyStructure stream_structure = CreateStreamStructure();
1476
1477 DependencyDescriptor keyframe_descriptor_without_structure;
1478 keyframe_descriptor_without_structure.frame_dependencies =
1479 stream_structure.templates[0];
1480 keyframe_descriptor_without_structure.frame_number = 0;
1481
philipel17093412022-06-13 11:14:431482 InjectPacketWith(stream_structure, keyframe_descriptor_without_structure);
1483
1484 // Not enough time since last keyframe request
1485 time_controller_.AdvanceTime(TimeDelta::Millis(500));
1486 InjectPacketWith(stream_structure, keyframe_descriptor_without_structure);
philipel27b35a72022-07-05 07:59:551487 EXPECT_THAT(rtcp_packet_parser_.pli()->num_packets(), Eq(1));
philipel17093412022-06-13 11:14:431488
1489 time_controller_.AdvanceTime(TimeDelta::Millis(501));
1490 InjectPacketWith(stream_structure, keyframe_descriptor_without_structure);
philipel27b35a72022-07-05 07:59:551491 EXPECT_THAT(rtcp_packet_parser_.pli()->num_packets(), Eq(2));
philipel17093412022-06-13 11:14:431492}
1493
philipel7aff4d12024-01-17 18:26:581494TEST_F(RtpVideoStreamReceiver2DependencyDescriptorTest,
1495 RetryStashedPacketsAfterReceivingScalabilityStructure) {
1496 FrameDependencyStructure stream_structure1 = CreateStreamStructure();
1497 FrameDependencyStructure stream_structure2 = CreateStreamStructure();
1498 // Make sure template ids for these two structures do not collide:
1499 // adjust structure_id (that is also used as template id offset).
1500 stream_structure1.structure_id = 13;
1501 stream_structure2.structure_id =
1502 stream_structure1.structure_id + stream_structure1.templates.size();
1503
1504 DependencyDescriptor keyframe1_descriptor;
1505 keyframe1_descriptor.attached_structure =
1506 std::make_unique<FrameDependencyStructure>(stream_structure1);
1507 keyframe1_descriptor.frame_dependencies = stream_structure1.templates[0];
1508 keyframe1_descriptor.frame_number = 1;
1509
1510 DependencyDescriptor keyframe2_descriptor;
1511 keyframe2_descriptor.attached_structure =
1512 std::make_unique<FrameDependencyStructure>(stream_structure2);
1513 keyframe2_descriptor.frame_dependencies = stream_structure2.templates[0];
1514 keyframe2_descriptor.frame_number = 2;
1515
1516 DependencyDescriptor deltaframe_descriptor;
1517 deltaframe_descriptor.frame_dependencies = stream_structure2.templates[1];
1518 deltaframe_descriptor.frame_number = 3;
1519
1520 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
1521 .WillOnce(
1522 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 1); })
1523 .WillOnce(
1524 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 2); })
1525 .WillOnce(
1526 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 3); });
1527
1528 InjectPacketWith(stream_structure1, keyframe1_descriptor);
1529 InjectPacketWith(stream_structure2, deltaframe_descriptor);
1530 InjectPacketWith(stream_structure2, keyframe2_descriptor);
1531}
1532
1533TEST_F(RtpVideoStreamReceiver2DependencyDescriptorTest,
1534 RetryStashedPacketsAfterReceivingEarlierScalabilityStructure) {
1535 FrameDependencyStructure stream_structure1 = CreateStreamStructure();
1536 FrameDependencyStructure stream_structure2 = CreateStreamStructure();
1537 FrameDependencyStructure stream_structure3 = CreateStreamStructure();
1538 // Make sure template ids for these two structures do not collide:
1539 // adjust structure_id (that is also used as template id offset).
1540 stream_structure1.structure_id = 13;
1541 stream_structure2.structure_id =
1542 stream_structure1.structure_id + stream_structure1.templates.size();
1543 stream_structure3.structure_id =
1544 stream_structure2.structure_id + stream_structure2.templates.size();
1545
1546 DependencyDescriptor keyframe1_descriptor;
1547 keyframe1_descriptor.attached_structure =
1548 std::make_unique<FrameDependencyStructure>(stream_structure1);
1549 keyframe1_descriptor.frame_dependencies = stream_structure1.templates[0];
1550 keyframe1_descriptor.frame_number = 1;
1551
1552 DependencyDescriptor keyframe2_descriptor;
1553 keyframe2_descriptor.attached_structure =
1554 std::make_unique<FrameDependencyStructure>(stream_structure2);
1555 keyframe2_descriptor.frame_dependencies = stream_structure2.templates[0];
1556 keyframe2_descriptor.frame_number = 2;
1557
1558 DependencyDescriptor deltaframe2_descriptor;
1559 deltaframe2_descriptor.frame_dependencies = stream_structure2.templates[1];
1560 deltaframe2_descriptor.frame_number = 3;
1561
1562 DependencyDescriptor keyframe3_descriptor;
1563 keyframe3_descriptor.attached_structure =
1564 std::make_unique<FrameDependencyStructure>(stream_structure3);
1565 keyframe3_descriptor.frame_dependencies = stream_structure3.templates[0];
1566 keyframe3_descriptor.frame_number = 4;
1567
1568 DependencyDescriptor deltaframe3_descriptor;
1569 deltaframe3_descriptor.frame_dependencies = stream_structure3.templates[1];
1570 deltaframe3_descriptor.frame_number = 5;
1571
1572 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame)
1573 .WillOnce(
1574 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 1); })
1575 .WillOnce(
1576 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 2); })
1577 .WillOnce(
1578 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 3); })
1579 .WillOnce(
1580 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 4); })
1581 .WillOnce(
1582 [&](EncodedFrame* frame) { EXPECT_EQ(frame->Id() & 0xFFFF, 5); });
1583
1584 InjectPacketWith(stream_structure1, keyframe1_descriptor);
1585 InjectPacketWith(stream_structure2, deltaframe2_descriptor);
1586 InjectPacketWith(stream_structure3, deltaframe3_descriptor);
1587 InjectPacketWith(stream_structure2, keyframe2_descriptor);
1588 InjectPacketWith(stream_structure3, keyframe3_descriptor);
1589}
1590
Tommid3807da2020-05-22 15:36:361591TEST_F(RtpVideoStreamReceiver2Test, TransformFrame) {
1592 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
Tomas Gunnarssonc1d58912021-04-22 17:21:431593 rtc::make_ref_counted<testing::NiceMock<MockFrameTransformer>>();
Tommid3807da2020-05-22 15:36:361594 EXPECT_CALL(*mock_frame_transformer,
1595 RegisterTransformedFrameSinkCallback(_, config_.rtp.remote_ssrc));
1596 auto receiver = std::make_unique<RtpVideoStreamReceiver2>(
Danil Chapovalove2fee232024-08-29 09:50:331597 env_, TaskQueueBase::Current(), &mock_transport_, nullptr, nullptr,
1598 &config_, rtp_receive_statistics_.get(), nullptr, nullptr,
1599 &nack_periodic_processor_, &mock_on_complete_frame_callback_, nullptr,
1600 mock_frame_transformer);
Danil Chapovalov5653c952021-08-10 14:57:561601 receiver->AddReceiveCodec(kPayloadType, kVideoCodecGeneric, {},
Niels Möller5401bad2020-08-11 10:17:421602 /*raw_payload=*/false);
Tommid3807da2020-05-22 15:36:361603
1604 RtpPacketReceived rtp_packet;
1605 rtp_packet.SetPayloadType(kPayloadType);
Ali Tofigh2ab914c2022-04-13 10:55:151606 rtc::CopyOnWriteBuffer data({'1', '2', '3', '4'});
Tommid3807da2020-05-22 15:36:361607 rtp_packet.SetSequenceNumber(1);
1608 RTPVideoHeader video_header =
1609 GetGenericVideoHeader(VideoFrameType::kVideoFrameKey);
1610 mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(),
1611 data.size());
1612 EXPECT_CALL(*mock_frame_transformer, Transform(_));
philipel7aff4d12024-01-17 18:26:581613 receiver->OnReceivedPayloadData(data, rtp_packet, video_header, 0);
Tommid3807da2020-05-22 15:36:361614
1615 EXPECT_CALL(*mock_frame_transformer,
1616 UnregisterTransformedFrameSinkCallback(config_.rtp.remote_ssrc));
1617 receiver = nullptr;
1618}
1619
1620// Test default behavior and when playout delay is overridden by field trial.
Danil Chapovalov7084e1b2023-08-23 11:16:221621VideoPlayoutDelay TransmittedPlayoutDelay() {
1622 return {TimeDelta::Millis(100), TimeDelta::Millis(200)};
1623}
1624VideoPlayoutDelay ForcedPlayoutDelay() {
1625 return {TimeDelta::Millis(70), TimeDelta::Millis(90)};
1626}
Tommid3807da2020-05-22 15:36:361627struct PlayoutDelayOptions {
1628 std::string field_trial;
Niels Möllerd381eed2020-09-02 13:34:401629 VideoPlayoutDelay expected_delay;
Tommid3807da2020-05-22 15:36:361630};
Danil Chapovalov7084e1b2023-08-23 11:16:221631PlayoutDelayOptions DefaultBehavior() {
1632 return {.field_trial = "", .expected_delay = TransmittedPlayoutDelay()};
1633}
1634PlayoutDelayOptions OverridePlayoutDelay() {
1635 return {.field_trial = "WebRTC-ForcePlayoutDelay/min_ms:70,max_ms:90/",
1636 .expected_delay = ForcedPlayoutDelay()};
1637}
Tommid3807da2020-05-22 15:36:361638
1639class RtpVideoStreamReceiver2TestPlayoutDelay
1640 : public RtpVideoStreamReceiver2Test,
1641 public ::testing::WithParamInterface<PlayoutDelayOptions> {
1642 protected:
1643 RtpVideoStreamReceiver2TestPlayoutDelay()
1644 : RtpVideoStreamReceiver2Test(GetParam().field_trial) {}
1645};
1646
1647INSTANTIATE_TEST_SUITE_P(PlayoutDelay,
1648 RtpVideoStreamReceiver2TestPlayoutDelay,
Danil Chapovalov7084e1b2023-08-23 11:16:221649 Values(DefaultBehavior(), OverridePlayoutDelay()));
Tommid3807da2020-05-22 15:36:361650
1651TEST_P(RtpVideoStreamReceiver2TestPlayoutDelay, PlayoutDelay) {
Ali Tofigh2ab914c2022-04-13 10:55:151652 rtc::CopyOnWriteBuffer payload_data({'1', '2', '3', '4'});
Tommid3807da2020-05-22 15:36:361653 RtpHeaderExtensionMap extension_map;
1654 extension_map.Register<PlayoutDelayLimits>(1);
1655 RtpPacketToSend packet_to_send(&extension_map);
1656 packet_to_send.SetPayloadType(kPayloadType);
1657 packet_to_send.SetSequenceNumber(1);
1658
1659 // Set playout delay on outgoing packet.
1660 EXPECT_TRUE(packet_to_send.SetExtension<PlayoutDelayLimits>(
Danil Chapovalov7084e1b2023-08-23 11:16:221661 TransmittedPlayoutDelay()));
Tommid3807da2020-05-22 15:36:361662 uint8_t* payload = packet_to_send.AllocatePayload(payload_data.size());
1663 memcpy(payload, payload_data.data(), payload_data.size());
1664
1665 RtpPacketReceived received_packet(&extension_map);
1666 received_packet.Parse(packet_to_send.data(), packet_to_send.size());
1667
1668 RTPVideoHeader video_header =
1669 GetGenericVideoHeader(VideoFrameType::kVideoFrameKey);
1670 mock_on_complete_frame_callback_.AppendExpectedBitstream(payload_data.data(),
1671 payload_data.size());
1672 // Expect the playout delay of encoded frame to be the same as the transmitted
1673 // playout delay unless it was overridden by a field trial.
1674 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_))
philipelca188092021-03-23 11:00:491675 .WillOnce(Invoke([expected_playout_delay =
1676 GetParam().expected_delay](EncodedFrame* frame) {
Danil Chapovalov06717772023-08-21 16:17:311677 EXPECT_EQ(frame->EncodedImage().PlayoutDelay(), expected_playout_delay);
Tommid3807da2020-05-22 15:36:361678 }));
1679 rtp_video_stream_receiver_->OnReceivedPayloadData(
philipel7aff4d12024-01-17 18:26:581680 received_packet.PayloadBuffer(), received_packet, video_header, 0);
Tommid3807da2020-05-22 15:36:361681}
1682
Jianjun Zhu326df692024-04-15 01:11:251683#ifdef RTC_ENABLE_H265
1684RTPVideoHeader GetDefaultH265VideoHeader() {
1685 RTPVideoHeader video_header;
1686 video_header.codec = kVideoCodecH265;
1687 return video_header;
1688}
1689
1690class RtpVideoStreamReceiver2TestH265 : public RtpVideoStreamReceiver2Test {
1691 protected:
1692 RtpVideoStreamReceiver2TestH265()
1693 : RtpVideoStreamReceiver2Test("WebRTC-Video-H26xPacketBuffer/Enabled/") {}
1694};
1695
1696TEST_F(RtpVideoStreamReceiver2TestH265, H265Bitstream) {
1697 constexpr int kH265PayloadType = 98;
1698 webrtc::CodecParameterMap codec_params;
1699 rtp_video_stream_receiver_->AddReceiveCodec(kH265PayloadType, kVideoCodecH265,
1700 codec_params,
1701 /*raw_payload=*/false);
1702 rtp_video_stream_receiver_->StartReceive();
1703
1704 // Data is generated by WebCodecs H265 encoder, with 720p fake media capturer.
1705 // IDR is not complete.
1706 constexpr uint8_t vps[] = {0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01,
1707 0xff, 0xff, 0x21, 0x40, 0x00, 0x00, 0x03, 0x00,
1708 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
1709 0x7b, 0x3c, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x04,
1710 0x00, 0x00, 0x03, 0x00, 0x79, 0x40};
1711 constexpr uint8_t sps[] = {
1712 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x21, 0x40, 0x00, 0x00, 0x03,
1713 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x7b, 0xa0, 0x02,
1714 0x80, 0x80, 0x2d, 0x16, 0x8f, 0x92, 0x46, 0xd9, 0x3f, 0xf6, 0x02, 0x80,
1715 0x10, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe6, 0x45,
1716 0xde, 0xf7, 0xe0, 0x04, 0x65, 0x00, 0x23, 0x28, 0x80};
1717 constexpr uint8_t pps[] = {0x00, 0x00, 0x00, 0x01, 0x44, 0x01,
1718 0xc0, 0x25, 0x64, 0xc0, 0xed, 0x90};
1719 constexpr uint8_t idr[] = {0x00, 0x00, 0x00, 0x01, 0x26, 0x01, 0xaf,
1720 0xb0, 0x87, 0x11, 0x7a, 0xc1, 0x45, 0x57,
1721 0x3f, 0xff, 0x57, 0x14, 0x5f, 0xf7, 0x7a,
1722 0x37, 0xfd, 0xe3, 0xd9};
1723
1724 RtpPacketReceived rtp_packet;
1725 rtp_packet.SetPayloadType(kPayloadType);
1726 rtp_packet.SetSequenceNumber(0);
1727 rtp_packet.SetPayloadType(kH265PayloadType);
1728 RTPVideoHeader video_header = GetDefaultH265VideoHeader();
1729 mock_on_complete_frame_callback_.AppendExpectedBitstream(vps, sizeof(vps));
1730 rtp_video_stream_receiver_->OnReceivedPayloadData(
1731 rtc::CopyOnWriteBuffer(vps, sizeof(vps)), rtp_packet, video_header, 0);
1732
1733 rtp_packet.SetSequenceNumber(1);
1734 mock_on_complete_frame_callback_.AppendExpectedBitstream(sps, sizeof(sps));
1735 rtp_video_stream_receiver_->OnReceivedPayloadData(
1736 rtc::CopyOnWriteBuffer(sps, sizeof(sps)), rtp_packet, video_header, 0);
1737
1738 rtp_packet.SetSequenceNumber(2);
1739 mock_on_complete_frame_callback_.AppendExpectedBitstream(pps, sizeof(pps));
1740 rtp_video_stream_receiver_->OnReceivedPayloadData(
1741 rtc::CopyOnWriteBuffer(pps, sizeof(pps)), rtp_packet, video_header, 0);
1742
1743 rtp_packet.SetSequenceNumber(3);
1744 rtp_packet.SetMarker(true);
1745 mock_on_complete_frame_callback_.AppendExpectedBitstream(idr, sizeof(idr));
1746 EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame(_));
1747 rtp_video_stream_receiver_->OnReceivedPayloadData(
1748 rtc::CopyOnWriteBuffer(idr, sizeof(idr)), rtp_packet, video_header, 0);
1749}
1750#endif // RTC_ENABLE_H265
1751
Tommid3807da2020-05-22 15:36:361752} // namespace webrtc