2011-12-16 14:31:37 +00:00
|
|
|
/*
|
2012-02-07 14:56:45 +00:00
|
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
2011-12-16 14:31:37 +00:00
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
2016-04-27 01:19:58 -07:00
|
|
|
#include <memory>
|
2015-12-10 05:05:27 -08:00
|
|
|
#include <vector>
|
|
|
|
|
|
2015-03-04 22:55:15 +00:00
|
|
|
#include "webrtc/base/buffer.h"
|
2016-07-13 09:11:28 -07:00
|
|
|
#include "webrtc/base/rate_limiter.h"
|
2016-10-25 07:04:37 -07:00
|
|
|
#include "webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h"
|
2015-11-04 08:31:52 +01:00
|
|
|
#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
|
|
|
|
|
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
|
|
|
|
|
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
2016-08-23 17:51:42 +02:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
|
2013-03-18 16:39:03 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
|
2012-11-13 21:12:39 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
|
2016-09-02 19:15:59 +02:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
|
2016-10-26 02:41:55 -07:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
|
2016-09-02 19:15:59 +02:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
2012-11-13 21:12:39 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_sender.h"
|
2015-03-04 22:55:15 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
|
2015-03-17 14:33:12 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
2016-11-29 02:24:18 -08:00
|
|
|
#include "webrtc/test/field_trial.h"
|
2016-09-30 22:29:43 -07:00
|
|
|
#include "webrtc/test/gmock.h"
|
|
|
|
|
#include "webrtc/test/gtest.h"
|
2013-12-04 10:24:26 +00:00
|
|
|
#include "webrtc/test/mock_transport.h"
|
2012-11-13 21:12:39 +00:00
|
|
|
#include "webrtc/typedefs.h"
|
2011-12-16 14:31:37 +00:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
2011-12-16 21:24:30 +00:00
|
|
|
namespace {
|
2013-05-16 11:10:31 +00:00
|
|
|
const int kTransmissionTimeOffsetExtensionId = 1;
|
|
|
|
|
const int kAbsoluteSendTimeExtensionId = 14;
|
2015-03-17 14:33:12 +00:00
|
|
|
const int kTransportSequenceNumberExtensionId = 13;
|
2011-12-16 21:24:30 +00:00
|
|
|
const int kPayload = 100;
|
2015-04-21 20:24:50 +08:00
|
|
|
const int kRtxPayload = 98;
|
2011-12-16 21:24:30 +00:00
|
|
|
const uint32_t kTimestamp = 10;
|
|
|
|
|
const uint16_t kSeqNum = 33;
|
2016-11-14 05:14:50 -08:00
|
|
|
const uint32_t kSsrc = 725242;
|
2011-12-16 21:24:30 +00:00
|
|
|
const int kMaxPacketLength = 1500;
|
2013-05-20 20:55:07 +00:00
|
|
|
const uint8_t kAudioLevel = 0x5a;
|
2015-03-17 14:33:12 +00:00
|
|
|
const uint16_t kTransportSequenceNumber = 0xaabbu;
|
2013-05-20 20:55:07 +00:00
|
|
|
const uint8_t kAudioLevelExtensionId = 9;
|
|
|
|
|
const int kAudioPayload = 103;
|
2013-12-13 09:46:59 +00:00
|
|
|
const uint64_t kStartTime = 123456789;
|
2014-07-15 15:25:39 +00:00
|
|
|
const size_t kMaxPaddingSize = 224u;
|
2015-03-04 22:55:15 +00:00
|
|
|
const int kVideoRotationExtensionId = 5;
|
2016-08-23 17:51:42 +02:00
|
|
|
const size_t kGenericHeaderLength = 1;
|
|
|
|
|
const uint8_t kPayloadData[] = {47, 11, 32, 93, 89};
|
2011-12-16 21:24:30 +00:00
|
|
|
|
2016-09-02 19:15:59 +02:00
|
|
|
using ::testing::_;
|
|
|
|
|
using ::testing::ElementsAreArray;
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2013-11-15 08:59:19 +00:00
|
|
|
uint64_t ConvertMsToAbsSendTime(int64_t time_ms) {
|
2015-10-21 13:41:48 +02:00
|
|
|
return (((time_ms << 18) + 500) / 1000) & 0x00ffffff;
|
2013-11-15 08:59:19 +00:00
|
|
|
}
|
|
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
class LoopbackTransportTest : public webrtc::Transport {
|
|
|
|
|
public:
|
2016-10-26 02:41:55 -07:00
|
|
|
LoopbackTransportTest() : total_bytes_sent_(0), last_packet_id_(-1) {
|
|
|
|
|
receivers_extensions_.Register(kRtpExtensionTransmissionTimeOffset,
|
|
|
|
|
kTransmissionTimeOffsetExtensionId);
|
|
|
|
|
receivers_extensions_.Register(kRtpExtensionAbsoluteSendTime,
|
|
|
|
|
kAbsoluteSendTimeExtensionId);
|
|
|
|
|
receivers_extensions_.Register(kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId);
|
|
|
|
|
receivers_extensions_.Register(kRtpExtensionVideoRotation,
|
|
|
|
|
kVideoRotationExtensionId);
|
|
|
|
|
receivers_extensions_.Register(kRtpExtensionAudioLevel,
|
|
|
|
|
kAudioLevelExtensionId);
|
2015-03-04 22:55:15 +00:00
|
|
|
}
|
2016-10-26 02:41:55 -07:00
|
|
|
|
2015-10-02 03:39:33 -07:00
|
|
|
bool SendRtp(const uint8_t* data,
|
|
|
|
|
size_t len,
|
|
|
|
|
const PacketOptions& options) override {
|
2016-01-27 12:58:51 +01:00
|
|
|
last_packet_id_ = options.packet_id;
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
total_bytes_sent_ += len;
|
2016-10-26 02:41:55 -07:00
|
|
|
sent_packets_.push_back(RtpPacketReceived(&receivers_extensions_));
|
|
|
|
|
EXPECT_TRUE(sent_packets_.back().Parse(data, len));
|
2015-09-28 09:59:31 -07:00
|
|
|
return true;
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
2015-12-10 02:39:40 -08:00
|
|
|
bool SendRtcp(const uint8_t* data, size_t len) override { return false; }
|
2016-10-26 02:41:55 -07:00
|
|
|
const RtpPacketReceived& last_sent_packet() { return sent_packets_.back(); }
|
|
|
|
|
int packets_sent() { return sent_packets_.size(); }
|
|
|
|
|
|
2014-07-10 16:24:54 +00:00
|
|
|
size_t total_bytes_sent_;
|
2016-01-27 12:58:51 +01:00
|
|
|
int last_packet_id_;
|
2016-10-26 02:41:55 -07:00
|
|
|
std::vector<RtpPacketReceived> sent_packets_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
RtpHeaderExtensionMap receivers_extensions_;
|
2012-01-16 11:06:31 +00:00
|
|
|
};
|
|
|
|
|
|
2015-03-04 22:55:15 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
2015-09-21 15:11:14 -07:00
|
|
|
class MockRtpPacketSender : public RtpPacketSender {
|
|
|
|
|
public:
|
|
|
|
|
MockRtpPacketSender() {}
|
|
|
|
|
virtual ~MockRtpPacketSender() {}
|
|
|
|
|
|
2015-10-08 11:44:14 +02:00
|
|
|
MOCK_METHOD6(InsertPacket,
|
|
|
|
|
void(Priority priority,
|
2015-09-21 15:11:14 -07:00
|
|
|
uint32_t ssrc,
|
|
|
|
|
uint16_t sequence_number,
|
|
|
|
|
int64_t capture_time_ms,
|
|
|
|
|
size_t bytes,
|
|
|
|
|
bool retransmission));
|
|
|
|
|
};
|
|
|
|
|
|
2016-01-27 12:58:51 +01:00
|
|
|
class MockTransportSequenceNumberAllocator
|
|
|
|
|
: public TransportSequenceNumberAllocator {
|
|
|
|
|
public:
|
|
|
|
|
MOCK_METHOD0(AllocateSequenceNumber, uint16_t());
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-02 23:44:01 -07:00
|
|
|
class MockSendPacketObserver : public SendPacketObserver {
|
|
|
|
|
public:
|
|
|
|
|
MOCK_METHOD3(OnSendPacket, void(uint16_t, int64_t, uint32_t));
|
|
|
|
|
};
|
|
|
|
|
|
2016-08-23 17:51:42 +02:00
|
|
|
class MockTransportFeedbackObserver : public TransportFeedbackObserver {
|
|
|
|
|
public:
|
|
|
|
|
MOCK_METHOD3(AddPacket, void(uint16_t, size_t, int));
|
|
|
|
|
MOCK_METHOD1(OnTransportFeedback, void(const rtcp::TransportFeedback&));
|
2016-09-07 09:58:20 +02:00
|
|
|
MOCK_CONST_METHOD0(GetTransportFeedbackVector, std::vector<PacketInfo>());
|
2016-08-23 17:51:42 +02:00
|
|
|
};
|
|
|
|
|
|
2011-12-16 14:31:37 +00:00
|
|
|
class RtpSenderTest : public ::testing::Test {
|
|
|
|
|
protected:
|
|
|
|
|
RtpSenderTest()
|
2013-12-13 09:46:59 +00:00
|
|
|
: fake_clock_(kStartTime),
|
2016-01-21 05:42:04 -08:00
|
|
|
mock_rtc_event_log_(),
|
2013-12-13 09:46:59 +00:00
|
|
|
mock_paced_sender_(),
|
2016-07-13 09:11:28 -07:00
|
|
|
retransmission_rate_limiter_(&fake_clock_, 1000),
|
2013-12-13 09:46:59 +00:00
|
|
|
rtp_sender_(),
|
|
|
|
|
payload_(kPayload),
|
|
|
|
|
transport_(),
|
2016-07-13 09:11:28 -07:00
|
|
|
kMarkerBit(true) {}
|
2013-05-20 20:55:07 +00:00
|
|
|
|
2015-10-08 11:44:14 +02:00
|
|
|
void SetUp() override { SetUpRtpSender(true); }
|
|
|
|
|
|
|
|
|
|
void SetUpRtpSender(bool pacer) {
|
2016-05-02 23:44:01 -07:00
|
|
|
rtp_sender_.reset(new RTPSender(
|
|
|
|
|
false, &fake_clock_, &transport_, pacer ? &mock_paced_sender_ : nullptr,
|
2016-11-10 05:04:48 -08:00
|
|
|
nullptr, &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
|
2016-07-13 09:11:28 -07:00
|
|
|
&mock_rtc_event_log_, &send_packet_observer_,
|
2016-11-17 01:38:43 -08:00
|
|
|
&retransmission_rate_limiter_, nullptr));
|
2016-08-03 18:27:40 +02:00
|
|
|
rtp_sender_->SetSendPayloadType(kPayload);
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->SetSequenceNumber(kSeqNum);
|
2016-08-18 02:01:49 -07:00
|
|
|
rtp_sender_->SetTimestampOffset(0);
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->SetSSRC(kSsrc);
|
2013-05-20 20:55:07 +00:00
|
|
|
}
|
|
|
|
|
|
2013-01-21 07:42:11 +00:00
|
|
|
SimulatedClock fake_clock_;
|
2016-07-28 07:56:38 -07:00
|
|
|
testing::NiceMock<MockRtcEventLog> mock_rtc_event_log_;
|
2015-09-21 15:11:14 -07:00
|
|
|
MockRtpPacketSender mock_paced_sender_;
|
2016-07-28 07:56:38 -07:00
|
|
|
testing::StrictMock<MockTransportSequenceNumberAllocator> seq_num_allocator_;
|
|
|
|
|
testing::StrictMock<MockSendPacketObserver> send_packet_observer_;
|
2016-08-23 17:51:42 +02:00
|
|
|
testing::StrictMock<MockTransportFeedbackObserver> feedback_observer_;
|
2016-07-13 09:11:28 -07:00
|
|
|
RateLimiter retransmission_rate_limiter_;
|
2016-04-27 01:19:58 -07:00
|
|
|
std::unique_ptr<RTPSender> rtp_sender_;
|
2013-05-20 20:55:07 +00:00
|
|
|
int payload_;
|
2012-01-16 11:06:31 +00:00
|
|
|
LoopbackTransportTest transport_;
|
2011-12-16 14:31:37 +00:00
|
|
|
const bool kMarkerBit;
|
|
|
|
|
|
2013-05-29 12:12:51 +00:00
|
|
|
void VerifyRTPHeaderCommon(const RTPHeader& rtp_header) {
|
2016-01-14 14:55:19 -08:00
|
|
|
VerifyRTPHeaderCommon(rtp_header, kMarkerBit, 0);
|
2015-03-04 22:55:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VerifyRTPHeaderCommon(const RTPHeader& rtp_header, bool marker_bit) {
|
2016-01-14 14:55:19 -08:00
|
|
|
VerifyRTPHeaderCommon(rtp_header, marker_bit, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VerifyRTPHeaderCommon(const RTPHeader& rtp_header,
|
|
|
|
|
bool marker_bit,
|
|
|
|
|
uint8_t number_of_csrcs) {
|
2015-03-04 22:55:15 +00:00
|
|
|
EXPECT_EQ(marker_bit, rtp_header.markerBit);
|
2013-05-29 12:12:51 +00:00
|
|
|
EXPECT_EQ(payload_, rtp_header.payloadType);
|
|
|
|
|
EXPECT_EQ(kSeqNum, rtp_header.sequenceNumber);
|
|
|
|
|
EXPECT_EQ(kTimestamp, rtp_header.timestamp);
|
|
|
|
|
EXPECT_EQ(rtp_sender_->SSRC(), rtp_header.ssrc);
|
2016-01-14 14:55:19 -08:00
|
|
|
EXPECT_EQ(number_of_csrcs, rtp_header.numCSRCs);
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
EXPECT_EQ(0U, rtp_header.paddingLength);
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
2013-12-04 10:24:26 +00:00
|
|
|
|
2016-10-19 06:11:39 -07:00
|
|
|
std::unique_ptr<RtpPacketToSend> BuildRtpPacket(int payload_type,
|
|
|
|
|
bool marker_bit,
|
|
|
|
|
uint32_t timestamp,
|
|
|
|
|
int64_t capture_time_ms) {
|
|
|
|
|
auto packet = rtp_sender_->AllocatePacket();
|
|
|
|
|
packet->SetPayloadType(payload_type);
|
|
|
|
|
packet->SetMarker(marker_bit);
|
|
|
|
|
packet->SetTimestamp(timestamp);
|
|
|
|
|
packet->set_capture_time_ms(capture_time_ms);
|
|
|
|
|
EXPECT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get()));
|
|
|
|
|
return packet;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-04 10:24:26 +00:00
|
|
|
void SendPacket(int64_t capture_time_ms, int payload_length) {
|
|
|
|
|
uint32_t timestamp = capture_time_ms * 90;
|
2016-10-19 06:11:39 -07:00
|
|
|
auto packet =
|
|
|
|
|
BuildRtpPacket(kPayload, kMarkerBit, timestamp, capture_time_ms);
|
|
|
|
|
packet->AllocatePayload(payload_length);
|
2013-12-04 10:24:26 +00:00
|
|
|
|
|
|
|
|
// Packet should be stored in a send bucket.
|
2016-10-19 06:11:39 -07:00
|
|
|
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
|
|
|
|
kAllowRetransmission,
|
|
|
|
|
RtpPacketSender::kNormalPriority));
|
2013-12-04 10:24:26 +00:00
|
|
|
}
|
2016-05-02 23:44:01 -07:00
|
|
|
|
|
|
|
|
void SendGenericPayload() {
|
|
|
|
|
const uint32_t kTimestamp = 1234;
|
|
|
|
|
const uint8_t kPayloadType = 127;
|
|
|
|
|
const int64_t kCaptureTimeMs = fake_clock_.TimeInMilliseconds();
|
|
|
|
|
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
|
|
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterPayload(payload_name, kPayloadType, 90000,
|
|
|
|
|
0, 1500));
|
|
|
|
|
|
2016-08-02 17:46:41 -07:00
|
|
|
EXPECT_TRUE(rtp_sender_->SendOutgoingData(
|
2016-08-23 17:51:42 +02:00
|
|
|
kVideoFrameKey, kPayloadType, kTimestamp, kCaptureTimeMs, kPayloadData,
|
|
|
|
|
sizeof(kPayloadData), nullptr, nullptr, nullptr));
|
2016-05-02 23:44:01 -07:00
|
|
|
}
|
2011-12-16 14:31:37 +00:00
|
|
|
};
|
|
|
|
|
|
2015-10-08 11:44:14 +02:00
|
|
|
// TODO(pbos): Move tests over from WithoutPacer to RtpSenderTest as this is our
|
|
|
|
|
// default code path.
|
|
|
|
|
class RtpSenderTestWithoutPacer : public RtpSenderTest {
|
|
|
|
|
public:
|
|
|
|
|
void SetUp() override { SetUpRtpSender(false); }
|
|
|
|
|
};
|
|
|
|
|
|
2015-03-04 22:55:15 +00:00
|
|
|
class RtpSenderVideoTest : public RtpSenderTest {
|
|
|
|
|
protected:
|
2015-12-10 02:39:40 -08:00
|
|
|
void SetUp() override {
|
2015-10-08 11:44:14 +02:00
|
|
|
// TODO(pbos): Set up to use pacer.
|
|
|
|
|
SetUpRtpSender(false);
|
2015-03-04 22:55:15 +00:00
|
|
|
rtp_sender_video_.reset(
|
2016-11-10 05:04:48 -08:00
|
|
|
new RTPSenderVideo(&fake_clock_, rtp_sender_.get(), nullptr));
|
2015-03-04 22:55:15 +00:00
|
|
|
}
|
2016-04-27 01:19:58 -07:00
|
|
|
std::unique_ptr<RTPSenderVideo> rtp_sender_video_;
|
2015-03-04 22:55:15 +00:00
|
|
|
};
|
|
|
|
|
|
2016-09-02 19:15:59 +02:00
|
|
|
TEST_F(RtpSenderTestWithoutPacer, AllocatePacketSetCsrc) {
|
|
|
|
|
// Configure rtp_sender with csrc.
|
|
|
|
|
std::vector<uint32_t> csrcs;
|
|
|
|
|
csrcs.push_back(0x23456789);
|
|
|
|
|
rtp_sender_->SetCsrcs(csrcs);
|
|
|
|
|
|
|
|
|
|
auto packet = rtp_sender_->AllocatePacket();
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(packet);
|
|
|
|
|
EXPECT_EQ(rtp_sender_->SSRC(), packet->Ssrc());
|
|
|
|
|
EXPECT_EQ(csrcs, packet->Csrcs());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTestWithoutPacer, AllocatePacketReserveExtensions) {
|
|
|
|
|
// Configure rtp_sender with extensions.
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransmissionTimeOffset,
|
|
|
|
|
kTransmissionTimeOffsetExtensionId));
|
|
|
|
|
ASSERT_EQ(
|
|
|
|
|
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
|
|
|
|
kAbsoluteSendTimeExtensionId));
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
|
|
|
|
|
kAudioLevelExtensionId));
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId));
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
|
|
|
|
|
|
|
|
|
auto packet = rtp_sender_->AllocatePacket();
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(packet);
|
|
|
|
|
// Preallocate BWE extensions RtpSender set itself.
|
|
|
|
|
EXPECT_TRUE(packet->HasExtension<TransmissionOffset>());
|
|
|
|
|
EXPECT_TRUE(packet->HasExtension<AbsoluteSendTime>());
|
|
|
|
|
EXPECT_TRUE(packet->HasExtension<TransportSequenceNumber>());
|
|
|
|
|
// Do not allocate media specific extensions.
|
|
|
|
|
EXPECT_FALSE(packet->HasExtension<AudioLevel>());
|
|
|
|
|
EXPECT_FALSE(packet->HasExtension<VideoOrientation>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberAdvanceSequenceNumber) {
|
|
|
|
|
auto packet = rtp_sender_->AllocatePacket();
|
|
|
|
|
ASSERT_TRUE(packet);
|
|
|
|
|
const uint16_t sequence_number = rtp_sender_->SequenceNumber();
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get()));
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(sequence_number, packet->SequenceNumber());
|
|
|
|
|
EXPECT_EQ(sequence_number + 1, rtp_sender_->SequenceNumber());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberFailsOnNotSending) {
|
|
|
|
|
auto packet = rtp_sender_->AllocatePacket();
|
|
|
|
|
ASSERT_TRUE(packet);
|
|
|
|
|
|
|
|
|
|
rtp_sender_->SetSendingMediaStatus(false);
|
|
|
|
|
EXPECT_FALSE(rtp_sender_->AssignSequenceNumber(packet.get()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberMayAllowPadding) {
|
|
|
|
|
constexpr size_t kPaddingSize = 100;
|
|
|
|
|
auto packet = rtp_sender_->AllocatePacket();
|
|
|
|
|
ASSERT_TRUE(packet);
|
|
|
|
|
|
2016-09-19 05:37:56 -07:00
|
|
|
ASSERT_FALSE(rtp_sender_->TimeToSendPadding(kPaddingSize, -1));
|
2016-09-02 19:15:59 +02:00
|
|
|
packet->SetMarker(false);
|
|
|
|
|
ASSERT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get()));
|
|
|
|
|
// Packet without marker bit doesn't allow padding.
|
2016-09-19 05:37:56 -07:00
|
|
|
EXPECT_FALSE(rtp_sender_->TimeToSendPadding(kPaddingSize, -1));
|
2016-09-02 19:15:59 +02:00
|
|
|
|
|
|
|
|
packet->SetMarker(true);
|
|
|
|
|
ASSERT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get()));
|
|
|
|
|
// Packet with marker bit allows send padding.
|
2016-09-19 05:37:56 -07:00
|
|
|
EXPECT_TRUE(rtp_sender_->TimeToSendPadding(kPaddingSize, -1));
|
2016-09-02 19:15:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberSetPaddingTimestamps) {
|
|
|
|
|
constexpr size_t kPaddingSize = 100;
|
|
|
|
|
auto packet = rtp_sender_->AllocatePacket();
|
|
|
|
|
ASSERT_TRUE(packet);
|
|
|
|
|
packet->SetMarker(true);
|
|
|
|
|
packet->SetTimestamp(kTimestamp);
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get()));
|
2016-09-19 05:37:56 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->TimeToSendPadding(kPaddingSize, -1));
|
2016-09-02 19:15:59 +02:00
|
|
|
|
|
|
|
|
ASSERT_EQ(1u, transport_.sent_packets_.size());
|
2016-10-26 02:41:55 -07:00
|
|
|
// Verify padding packet timestamp.
|
|
|
|
|
EXPECT_EQ(kTimestamp, transport_.last_sent_packet().Timestamp());
|
2016-09-02 19:15:59 +02:00
|
|
|
}
|
|
|
|
|
|
2016-01-27 12:58:51 +01:00
|
|
|
TEST_F(RtpSenderTestWithoutPacer, SendsPacketsWithTransportSequenceNumber) {
|
2016-08-23 17:51:42 +02:00
|
|
|
rtp_sender_.reset(new RTPSender(
|
2016-11-10 05:04:48 -08:00
|
|
|
false, &fake_clock_, &transport_, nullptr, nullptr, &seq_num_allocator_,
|
|
|
|
|
&feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
|
2016-11-17 01:38:43 -08:00
|
|
|
&send_packet_observer_, &retransmission_rate_limiter_, nullptr));
|
2016-01-27 12:58:51 +01:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId));
|
|
|
|
|
|
|
|
|
|
EXPECT_CALL(seq_num_allocator_, AllocateSequenceNumber())
|
|
|
|
|
.WillOnce(testing::Return(kTransportSequenceNumber));
|
2016-05-02 23:44:01 -07:00
|
|
|
EXPECT_CALL(send_packet_observer_,
|
|
|
|
|
OnSendPacket(kTransportSequenceNumber, _, _))
|
|
|
|
|
.Times(1);
|
2016-08-23 17:51:42 +02:00
|
|
|
EXPECT_CALL(feedback_observer_,
|
|
|
|
|
AddPacket(kTransportSequenceNumber,
|
|
|
|
|
sizeof(kPayloadData) + kGenericHeaderLength,
|
|
|
|
|
PacketInfo::kNotAProbe))
|
|
|
|
|
.Times(1);
|
2016-05-02 23:44:01 -07:00
|
|
|
|
|
|
|
|
SendGenericPayload();
|
2016-01-27 12:58:51 +01:00
|
|
|
|
2016-10-26 02:41:55 -07:00
|
|
|
const auto& packet = transport_.last_sent_packet();
|
|
|
|
|
uint16_t transport_seq_no;
|
|
|
|
|
ASSERT_TRUE(packet.GetExtension<TransportSequenceNumber>(&transport_seq_no));
|
|
|
|
|
EXPECT_EQ(kTransportSequenceNumber, transport_seq_no);
|
|
|
|
|
EXPECT_EQ(transport_.last_packet_id_, transport_seq_no);
|
2016-01-27 12:58:51 +01:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 07:56:38 -07:00
|
|
|
TEST_F(RtpSenderTestWithoutPacer, NoAllocationIfNotRegistered) {
|
|
|
|
|
SendGenericPayload();
|
|
|
|
|
}
|
2016-05-02 23:44:01 -07:00
|
|
|
|
2016-07-28 07:56:38 -07:00
|
|
|
TEST_F(RtpSenderTestWithoutPacer, OnSendPacketUpdated) {
|
|
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId));
|
2016-05-02 23:44:01 -07:00
|
|
|
EXPECT_CALL(seq_num_allocator_, AllocateSequenceNumber())
|
|
|
|
|
.WillOnce(testing::Return(kTransportSequenceNumber));
|
|
|
|
|
EXPECT_CALL(send_packet_observer_,
|
|
|
|
|
OnSendPacket(kTransportSequenceNumber, _, _))
|
|
|
|
|
.Times(1);
|
|
|
|
|
|
|
|
|
|
SendGenericPayload();
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-23 17:51:42 +02:00
|
|
|
TEST_F(RtpSenderTest, SendsPacketsWithTransportSequenceNumber) {
|
2016-11-17 01:38:43 -08:00
|
|
|
rtp_sender_.reset(new RTPSender(
|
|
|
|
|
false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr,
|
|
|
|
|
&seq_num_allocator_, &feedback_observer_, nullptr, nullptr, nullptr,
|
|
|
|
|
&mock_rtc_event_log_, &send_packet_observer_,
|
|
|
|
|
&retransmission_rate_limiter_, nullptr));
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->SetSequenceNumber(kSeqNum);
|
|
|
|
|
rtp_sender_->SetSSRC(kSsrc);
|
2016-08-23 17:51:42 +02:00
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
|
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId));
|
|
|
|
|
|
2016-11-14 05:14:50 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(_, kSsrc, kSeqNum, _, _, _));
|
2016-08-23 17:51:42 +02:00
|
|
|
EXPECT_CALL(seq_num_allocator_, AllocateSequenceNumber())
|
|
|
|
|
.WillOnce(testing::Return(kTransportSequenceNumber));
|
|
|
|
|
EXPECT_CALL(send_packet_observer_,
|
|
|
|
|
OnSendPacket(kTransportSequenceNumber, _, _))
|
|
|
|
|
.Times(1);
|
|
|
|
|
const int kProbeClusterId = 1;
|
|
|
|
|
EXPECT_CALL(
|
|
|
|
|
feedback_observer_,
|
|
|
|
|
AddPacket(kTransportSequenceNumber,
|
|
|
|
|
sizeof(kPayloadData) + kGenericHeaderLength, kProbeClusterId))
|
|
|
|
|
.Times(1);
|
|
|
|
|
|
|
|
|
|
SendGenericPayload();
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(
|
|
|
|
|
kSsrc, kSeqNum, fake_clock_.TimeInMilliseconds(), false, kProbeClusterId);
|
2016-08-23 17:51:42 +02:00
|
|
|
|
2016-10-26 02:41:55 -07:00
|
|
|
const auto& packet = transport_.last_sent_packet();
|
|
|
|
|
uint16_t transport_seq_no;
|
|
|
|
|
EXPECT_TRUE(packet.GetExtension<TransportSequenceNumber>(&transport_seq_no));
|
|
|
|
|
EXPECT_EQ(kTransportSequenceNumber, transport_seq_no);
|
|
|
|
|
EXPECT_EQ(transport_.last_packet_id_, transport_seq_no);
|
2016-08-23 17:51:42 +02:00
|
|
|
}
|
|
|
|
|
|
2013-05-16 11:10:31 +00:00
|
|
|
TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
|
2015-10-08 11:44:14 +02:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority,
|
2016-11-14 05:14:50 -08:00
|
|
|
kSsrc, kSeqNum, _, _, _));
|
2016-01-21 05:42:04 -08:00
|
|
|
EXPECT_CALL(mock_rtc_event_log_,
|
|
|
|
|
LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _));
|
2013-04-27 00:41:08 +00:00
|
|
|
|
|
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
2013-05-16 11:10:31 +00:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
2015-12-10 02:39:40 -08:00
|
|
|
kRtpExtensionTransmissionTimeOffset,
|
|
|
|
|
kTransmissionTimeOffsetExtensionId));
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
|
|
|
|
kAbsoluteSendTimeExtensionId));
|
2013-06-19 14:13:42 +00:00
|
|
|
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
|
2016-10-19 06:11:39 -07:00
|
|
|
auto packet =
|
|
|
|
|
BuildRtpPacket(kPayload, kMarkerBit, kTimestamp, capture_time_ms);
|
|
|
|
|
size_t packet_size = packet->size();
|
2013-04-27 00:41:08 +00:00
|
|
|
|
|
|
|
|
// Packet should be stored in a send bucket.
|
2016-10-19 06:11:39 -07:00
|
|
|
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
|
|
|
|
kAllowRetransmission,
|
2016-08-02 17:46:41 -07:00
|
|
|
RtpPacketSender::kNormalPriority));
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(0, transport_.packets_sent());
|
2013-04-27 00:41:08 +00:00
|
|
|
|
|
|
|
|
const int kStoredTimeInMs = 100;
|
|
|
|
|
fake_clock_.AdvanceTimeMilliseconds(kStoredTimeInMs);
|
|
|
|
|
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum, capture_time_ms, false,
|
2016-06-01 06:31:17 -07:00
|
|
|
PacketInfo::kNotAProbe);
|
2013-04-27 00:41:08 +00:00
|
|
|
|
|
|
|
|
// Process send bucket. Packet should now be sent.
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(1, transport_.packets_sent());
|
|
|
|
|
EXPECT_EQ(packet_size, transport_.last_sent_packet().size());
|
|
|
|
|
|
2013-05-29 12:12:51 +00:00
|
|
|
webrtc::RTPHeader rtp_header;
|
2016-10-26 02:41:55 -07:00
|
|
|
transport_.last_sent_packet().GetHeader(&rtp_header);
|
2013-04-27 00:41:08 +00:00
|
|
|
|
|
|
|
|
// Verify transmission time offset.
|
|
|
|
|
EXPECT_EQ(kStoredTimeInMs * 90, rtp_header.extension.transmissionTimeOffset);
|
2013-05-16 11:10:31 +00:00
|
|
|
uint64_t expected_send_time =
|
2013-11-15 08:59:19 +00:00
|
|
|
ConvertMsToAbsSendTime(fake_clock_.TimeInMilliseconds());
|
2013-05-16 11:10:31 +00:00
|
|
|
EXPECT_EQ(expected_send_time, rtp_header.extension.absoluteSendTime);
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
2013-04-27 00:41:08 +00:00
|
|
|
TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
|
2015-10-08 11:44:14 +02:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority,
|
2016-11-14 05:14:50 -08:00
|
|
|
kSsrc, kSeqNum, _, _, _));
|
2016-01-21 05:42:04 -08:00
|
|
|
EXPECT_CALL(mock_rtc_event_log_,
|
|
|
|
|
LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _));
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2012-11-07 17:01:04 +00:00
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
2013-05-16 11:10:31 +00:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
2015-12-10 02:39:40 -08:00
|
|
|
kRtpExtensionTransmissionTimeOffset,
|
|
|
|
|
kTransmissionTimeOffsetExtensionId));
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
|
|
|
|
kAbsoluteSendTimeExtensionId));
|
2013-06-19 14:13:42 +00:00
|
|
|
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
|
2016-10-19 06:11:39 -07:00
|
|
|
auto packet =
|
|
|
|
|
BuildRtpPacket(kPayload, kMarkerBit, kTimestamp, capture_time_ms);
|
|
|
|
|
size_t packet_size = packet->size();
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
// Packet should be stored in a send bucket.
|
2016-10-19 06:11:39 -07:00
|
|
|
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
|
|
|
|
kAllowRetransmission,
|
2016-08-02 17:46:41 -07:00
|
|
|
RtpPacketSender::kNormalPriority));
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(0, transport_.packets_sent());
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2016-01-14 14:37:39 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority,
|
2016-11-14 05:14:50 -08:00
|
|
|
kSsrc, kSeqNum, _, _, _));
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
const int kStoredTimeInMs = 100;
|
2013-01-21 07:42:11 +00:00
|
|
|
fake_clock_.AdvanceTimeMilliseconds(kStoredTimeInMs);
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2016-10-19 06:11:39 -07:00
|
|
|
EXPECT_EQ(static_cast<int>(packet_size), rtp_sender_->ReSendPacket(kSeqNum));
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(0, transport_.packets_sent());
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum, capture_time_ms, false,
|
2016-06-01 06:31:17 -07:00
|
|
|
PacketInfo::kNotAProbe);
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
// Process send bucket. Packet should now be sent.
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(1, transport_.packets_sent());
|
|
|
|
|
EXPECT_EQ(packet_size, transport_.last_sent_packet().size());
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2013-05-29 12:12:51 +00:00
|
|
|
webrtc::RTPHeader rtp_header;
|
2016-10-26 02:41:55 -07:00
|
|
|
transport_.last_sent_packet().GetHeader(&rtp_header);
|
2013-04-27 00:41:08 +00:00
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
// Verify transmission time offset.
|
|
|
|
|
EXPECT_EQ(kStoredTimeInMs * 90, rtp_header.extension.transmissionTimeOffset);
|
2013-05-16 11:10:31 +00:00
|
|
|
uint64_t expected_send_time =
|
2013-11-15 08:59:19 +00:00
|
|
|
ConvertMsToAbsSendTime(fake_clock_.TimeInMilliseconds());
|
|
|
|
|
EXPECT_EQ(expected_send_time, rtp_header.extension.absoluteSendTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This test sends 1 regular video packet, then 4 padding packets, and then
|
|
|
|
|
// 1 more regular packet.
|
|
|
|
|
TEST_F(RtpSenderTest, SendPadding) {
|
|
|
|
|
// Make all (non-padding) packets go to send queue.
|
2016-01-14 14:37:39 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority,
|
2016-11-14 05:14:50 -08:00
|
|
|
kSsrc, kSeqNum, _, _, _));
|
2016-01-21 05:42:04 -08:00
|
|
|
EXPECT_CALL(mock_rtc_event_log_,
|
|
|
|
|
LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _))
|
|
|
|
|
.Times(1 + 4 + 1);
|
2013-11-15 08:59:19 +00:00
|
|
|
|
|
|
|
|
uint16_t seq_num = kSeqNum;
|
|
|
|
|
uint32_t timestamp = kTimestamp;
|
|
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
size_t rtp_header_len = kRtpHeaderSize;
|
2013-11-15 08:59:19 +00:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
2015-12-10 02:39:40 -08:00
|
|
|
kRtpExtensionTransmissionTimeOffset,
|
|
|
|
|
kTransmissionTimeOffsetExtensionId));
|
2013-11-15 08:59:19 +00:00
|
|
|
rtp_header_len += 4; // 4 bytes extension.
|
2015-12-10 02:39:40 -08:00
|
|
|
EXPECT_EQ(
|
|
|
|
|
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
|
|
|
|
kAbsoluteSendTimeExtensionId));
|
2013-11-15 08:59:19 +00:00
|
|
|
rtp_header_len += 4; // 4 bytes extension.
|
|
|
|
|
rtp_header_len += 4; // 4 extra bytes common to all extension headers.
|
|
|
|
|
|
|
|
|
|
webrtc::RTPHeader rtp_header;
|
|
|
|
|
|
|
|
|
|
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
|
2016-10-19 06:11:39 -07:00
|
|
|
auto packet =
|
|
|
|
|
BuildRtpPacket(kPayload, kMarkerBit, timestamp, capture_time_ms);
|
2015-09-18 11:14:31 +02:00
|
|
|
const uint32_t media_packet_timestamp = timestamp;
|
2016-10-19 06:11:39 -07:00
|
|
|
size_t packet_size = packet->size();
|
2013-11-15 08:59:19 +00:00
|
|
|
|
|
|
|
|
// Packet should be stored in a send bucket.
|
2016-10-19 06:11:39 -07:00
|
|
|
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
|
|
|
|
kAllowRetransmission,
|
2016-08-02 17:46:41 -07:00
|
|
|
RtpPacketSender::kNormalPriority));
|
2013-11-15 08:59:19 +00:00
|
|
|
|
|
|
|
|
int total_packets_sent = 0;
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(total_packets_sent, transport_.packets_sent());
|
2013-11-15 08:59:19 +00:00
|
|
|
|
|
|
|
|
const int kStoredTimeInMs = 100;
|
|
|
|
|
fake_clock_.AdvanceTimeMilliseconds(kStoredTimeInMs);
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(kSsrc, seq_num++, capture_time_ms, false,
|
2016-06-01 06:31:17 -07:00
|
|
|
PacketInfo::kNotAProbe);
|
2013-11-15 08:59:19 +00:00
|
|
|
// Packet should now be sent. This test doesn't verify the regular video
|
|
|
|
|
// packet, since it is tested in another test.
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(++total_packets_sent, transport_.packets_sent());
|
2013-11-15 08:59:19 +00:00
|
|
|
timestamp += 90 * kStoredTimeInMs;
|
|
|
|
|
|
|
|
|
|
// Send padding 4 times, waiting 50 ms between each.
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
|
const int kPaddingPeriodMs = 50;
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
const size_t kPaddingBytes = 100;
|
|
|
|
|
const size_t kMaxPaddingLength = 224; // Value taken from rtp_sender.cc.
|
2013-11-15 08:59:19 +00:00
|
|
|
// Padding will be forced to full packets.
|
2016-06-01 06:31:17 -07:00
|
|
|
EXPECT_EQ(kMaxPaddingLength, rtp_sender_->TimeToSendPadding(
|
|
|
|
|
kPaddingBytes, PacketInfo::kNotAProbe));
|
2013-11-15 08:59:19 +00:00
|
|
|
|
|
|
|
|
// Process send bucket. Padding should now be sent.
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(++total_packets_sent, transport_.packets_sent());
|
2013-11-15 08:59:19 +00:00
|
|
|
EXPECT_EQ(kMaxPaddingLength + rtp_header_len,
|
2016-10-26 02:41:55 -07:00
|
|
|
transport_.last_sent_packet().size());
|
|
|
|
|
|
|
|
|
|
transport_.last_sent_packet().GetHeader(&rtp_header);
|
2015-07-01 05:35:53 -07:00
|
|
|
EXPECT_EQ(kMaxPaddingLength, rtp_header.paddingLength);
|
2013-11-15 08:59:19 +00:00
|
|
|
|
2015-09-18 11:14:31 +02:00
|
|
|
// Verify sequence number and timestamp. The timestamp should be the same
|
|
|
|
|
// as the last media packet.
|
2013-11-15 08:59:19 +00:00
|
|
|
EXPECT_EQ(seq_num++, rtp_header.sequenceNumber);
|
2015-09-18 11:14:31 +02:00
|
|
|
EXPECT_EQ(media_packet_timestamp, rtp_header.timestamp);
|
2013-11-15 08:59:19 +00:00
|
|
|
// Verify transmission time offset.
|
2015-09-18 11:14:31 +02:00
|
|
|
int offset = timestamp - media_packet_timestamp;
|
|
|
|
|
EXPECT_EQ(offset, rtp_header.extension.transmissionTimeOffset);
|
2013-11-15 08:59:19 +00:00
|
|
|
uint64_t expected_send_time =
|
|
|
|
|
ConvertMsToAbsSendTime(fake_clock_.TimeInMilliseconds());
|
|
|
|
|
EXPECT_EQ(expected_send_time, rtp_header.extension.absoluteSendTime);
|
|
|
|
|
fake_clock_.AdvanceTimeMilliseconds(kPaddingPeriodMs);
|
|
|
|
|
timestamp += 90 * kPaddingPeriodMs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Send a regular video packet again.
|
|
|
|
|
capture_time_ms = fake_clock_.TimeInMilliseconds();
|
2016-10-19 06:11:39 -07:00
|
|
|
packet = BuildRtpPacket(kPayload, kMarkerBit, timestamp, capture_time_ms);
|
|
|
|
|
packet_size = packet->size();
|
2013-11-15 08:59:19 +00:00
|
|
|
|
2016-11-14 05:14:50 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kNormalPriority,
|
|
|
|
|
kSsrc, seq_num, _, _, _));
|
2016-01-14 14:37:39 -08:00
|
|
|
|
2013-11-15 08:59:19 +00:00
|
|
|
// Packet should be stored in a send bucket.
|
2016-10-19 06:11:39 -07:00
|
|
|
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
|
|
|
|
kAllowRetransmission,
|
2016-08-02 17:46:41 -07:00
|
|
|
RtpPacketSender::kNormalPriority));
|
2013-11-15 08:59:19 +00:00
|
|
|
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(kSsrc, seq_num, capture_time_ms, false,
|
2016-06-01 06:31:17 -07:00
|
|
|
PacketInfo::kNotAProbe);
|
2013-11-15 08:59:19 +00:00
|
|
|
// Process send bucket.
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(++total_packets_sent, transport_.packets_sent());
|
|
|
|
|
EXPECT_EQ(packet_size, transport_.last_sent_packet().size());
|
|
|
|
|
transport_.last_sent_packet().GetHeader(&rtp_header);
|
2013-11-15 08:59:19 +00:00
|
|
|
|
|
|
|
|
// Verify sequence number and timestamp.
|
|
|
|
|
EXPECT_EQ(seq_num, rtp_header.sequenceNumber);
|
|
|
|
|
EXPECT_EQ(timestamp, rtp_header.timestamp);
|
|
|
|
|
// Verify transmission time offset. This packet is sent without delay.
|
|
|
|
|
EXPECT_EQ(0, rtp_header.extension.transmissionTimeOffset);
|
|
|
|
|
uint64_t expected_send_time =
|
|
|
|
|
ConvertMsToAbsSendTime(fake_clock_.TimeInMilliseconds());
|
2013-05-16 11:10:31 +00:00
|
|
|
EXPECT_EQ(expected_send_time, rtp_header.extension.absoluteSendTime);
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
2013-03-18 16:39:03 +00:00
|
|
|
|
2016-05-02 23:44:01 -07:00
|
|
|
TEST_F(RtpSenderTest, OnSendPacketUpdated) {
|
2016-07-28 07:56:38 -07:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId));
|
2016-05-02 23:44:01 -07:00
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
|
|
|
|
|
|
|
|
|
EXPECT_CALL(send_packet_observer_,
|
|
|
|
|
OnSendPacket(kTransportSequenceNumber, _, _))
|
|
|
|
|
.Times(1);
|
|
|
|
|
EXPECT_CALL(seq_num_allocator_, AllocateSequenceNumber())
|
|
|
|
|
.WillOnce(testing::Return(kTransportSequenceNumber));
|
2016-11-14 05:14:50 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(_, kSsrc, kSeqNum, _, _, _))
|
|
|
|
|
.Times(1);
|
2016-05-02 23:44:01 -07:00
|
|
|
|
|
|
|
|
SendGenericPayload(); // Packet passed to pacer.
|
|
|
|
|
const bool kIsRetransmit = false;
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum,
|
|
|
|
|
fake_clock_.TimeInMilliseconds(), kIsRetransmit,
|
|
|
|
|
PacketInfo::kNotAProbe);
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(1, transport_.packets_sent());
|
2016-05-02 23:44:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTest, OnSendPacketNotUpdatedForRetransmits) {
|
2016-07-28 07:56:38 -07:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId));
|
2016-05-02 23:44:01 -07:00
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
|
|
|
|
|
|
|
|
|
EXPECT_CALL(send_packet_observer_, OnSendPacket(_, _, _)).Times(0);
|
|
|
|
|
EXPECT_CALL(seq_num_allocator_, AllocateSequenceNumber())
|
|
|
|
|
.WillOnce(testing::Return(kTransportSequenceNumber));
|
2016-11-14 05:14:50 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(_, kSsrc, kSeqNum, _, _, _))
|
|
|
|
|
.Times(1);
|
2016-05-02 23:44:01 -07:00
|
|
|
|
|
|
|
|
SendGenericPayload(); // Packet passed to pacer.
|
|
|
|
|
const bool kIsRetransmit = true;
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum,
|
|
|
|
|
fake_clock_.TimeInMilliseconds(), kIsRetransmit,
|
|
|
|
|
PacketInfo::kNotAProbe);
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(1, transport_.packets_sent());
|
2016-05-02 23:44:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTest, OnSendPacketNotUpdatedWithoutSeqNumAllocator) {
|
|
|
|
|
rtp_sender_.reset(new RTPSender(
|
2016-11-10 05:04:48 -08:00
|
|
|
false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr,
|
2016-05-02 23:44:01 -07:00
|
|
|
nullptr /* TransportSequenceNumberAllocator */, nullptr, nullptr, nullptr,
|
2016-11-17 01:38:43 -08:00
|
|
|
nullptr, nullptr, &send_packet_observer_, &retransmission_rate_limiter_,
|
|
|
|
|
nullptr));
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->SetSequenceNumber(kSeqNum);
|
|
|
|
|
rtp_sender_->SetSSRC(kSsrc);
|
2016-07-28 07:56:38 -07:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId));
|
2016-05-02 23:44:01 -07:00
|
|
|
rtp_sender_->SetSequenceNumber(kSeqNum);
|
|
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
|
|
|
|
|
|
|
|
|
EXPECT_CALL(send_packet_observer_, OnSendPacket(_, _, _)).Times(0);
|
2016-11-14 05:14:50 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(_, kSsrc, kSeqNum, _, _, _))
|
|
|
|
|
.Times(1);
|
2016-05-02 23:44:01 -07:00
|
|
|
|
|
|
|
|
SendGenericPayload(); // Packet passed to pacer.
|
|
|
|
|
const bool kIsRetransmit = false;
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum,
|
|
|
|
|
fake_clock_.TimeInMilliseconds(), kIsRetransmit,
|
|
|
|
|
PacketInfo::kNotAProbe);
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(1, transport_.packets_sent());
|
2016-05-02 23:44:01 -07:00
|
|
|
}
|
|
|
|
|
|
2013-12-04 10:24:26 +00:00
|
|
|
TEST_F(RtpSenderTest, SendRedundantPayloads) {
|
|
|
|
|
MockTransport transport;
|
2016-01-21 05:42:04 -08:00
|
|
|
rtp_sender_.reset(new RTPSender(
|
2016-05-02 23:44:01 -07:00
|
|
|
false, &fake_clock_, &transport, &mock_paced_sender_, nullptr, nullptr,
|
2016-11-10 05:04:48 -08:00
|
|
|
nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr,
|
2016-11-17 01:38:43 -08:00
|
|
|
&retransmission_rate_limiter_, nullptr));
|
2013-12-04 10:24:26 +00:00
|
|
|
rtp_sender_->SetSequenceNumber(kSeqNum);
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->SetSSRC(kSsrc);
|
2015-04-21 20:24:50 +08:00
|
|
|
rtp_sender_->SetRtxPayloadType(kRtxPayload, kPayload);
|
2013-12-04 10:24:26 +00:00
|
|
|
|
|
|
|
|
uint16_t seq_num = kSeqNum;
|
|
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
2014-03-06 23:49:08 +00:00
|
|
|
int32_t rtp_header_len = kRtpHeaderSize;
|
2015-12-10 02:39:40 -08:00
|
|
|
EXPECT_EQ(
|
|
|
|
|
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
|
|
|
|
kAbsoluteSendTimeExtensionId));
|
2013-12-04 10:24:26 +00:00
|
|
|
rtp_header_len += 4; // 4 bytes extension.
|
|
|
|
|
rtp_header_len += 4; // 4 extra bytes common to all extension headers.
|
|
|
|
|
|
2015-01-13 14:15:15 +00:00
|
|
|
rtp_sender_->SetRtxStatus(kRtxRetransmitted | kRtxRedundantPayloads);
|
2014-06-05 08:25:29 +00:00
|
|
|
rtp_sender_->SetRtxSsrc(1234);
|
2013-12-04 10:24:26 +00:00
|
|
|
|
|
|
|
|
const size_t kNumPayloadSizes = 10;
|
2015-12-10 02:39:40 -08:00
|
|
|
const size_t kPayloadSizes[kNumPayloadSizes] = {500, 550, 600, 650, 700,
|
|
|
|
|
750, 800, 850, 900, 950};
|
2016-01-14 14:37:39 -08:00
|
|
|
// Expect all packets go through the pacer.
|
|
|
|
|
EXPECT_CALL(mock_paced_sender_,
|
2016-11-14 05:14:50 -08:00
|
|
|
InsertPacket(RtpPacketSender::kNormalPriority, kSsrc, _, _, _, _))
|
2016-01-14 14:37:39 -08:00
|
|
|
.Times(kNumPayloadSizes);
|
2016-01-21 05:42:04 -08:00
|
|
|
EXPECT_CALL(mock_rtc_event_log_,
|
|
|
|
|
LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _))
|
|
|
|
|
.Times(kNumPayloadSizes);
|
|
|
|
|
|
2013-12-04 10:24:26 +00:00
|
|
|
// Send 10 packets of increasing size.
|
|
|
|
|
for (size_t i = 0; i < kNumPayloadSizes; ++i) {
|
|
|
|
|
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
|
2015-10-02 03:39:33 -07:00
|
|
|
EXPECT_CALL(transport, SendRtp(_, _, _)).WillOnce(testing::Return(true));
|
2013-12-04 10:24:26 +00:00
|
|
|
SendPacket(capture_time_ms, kPayloadSizes[i]);
|
2016-11-14 05:14:50 -08:00
|
|
|
rtp_sender_->TimeToSendPacket(kSsrc, seq_num++, capture_time_ms, false,
|
2016-06-01 06:31:17 -07:00
|
|
|
PacketInfo::kNotAProbe);
|
2013-12-04 10:24:26 +00:00
|
|
|
fake_clock_.AdvanceTimeMilliseconds(33);
|
|
|
|
|
}
|
2016-01-21 05:42:04 -08:00
|
|
|
|
|
|
|
|
EXPECT_CALL(mock_rtc_event_log_,
|
|
|
|
|
LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _))
|
|
|
|
|
.Times(::testing::AtLeast(4));
|
|
|
|
|
|
2013-12-04 10:24:26 +00:00
|
|
|
// The amount of padding to send it too small to send a payload packet.
|
2015-10-02 03:39:33 -07:00
|
|
|
EXPECT_CALL(transport, SendRtp(_, kMaxPaddingSize + rtp_header_len, _))
|
2015-09-28 09:59:31 -07:00
|
|
|
.WillOnce(testing::Return(true));
|
2016-06-01 06:31:17 -07:00
|
|
|
EXPECT_EQ(kMaxPaddingSize,
|
|
|
|
|
rtp_sender_->TimeToSendPadding(49, PacketInfo::kNotAProbe));
|
2013-12-04 10:24:26 +00:00
|
|
|
|
2015-09-17 23:03:57 +02:00
|
|
|
EXPECT_CALL(transport,
|
2015-10-02 03:39:33 -07:00
|
|
|
SendRtp(_, kPayloadSizes[0] + rtp_header_len + kRtxHeaderSize, _))
|
2015-09-28 09:59:31 -07:00
|
|
|
.WillOnce(testing::Return(true));
|
2016-06-01 06:31:17 -07:00
|
|
|
EXPECT_EQ(kPayloadSizes[0],
|
|
|
|
|
rtp_sender_->TimeToSendPadding(500, PacketInfo::kNotAProbe));
|
2013-12-04 10:24:26 +00:00
|
|
|
|
2015-09-28 09:59:31 -07:00
|
|
|
EXPECT_CALL(transport, SendRtp(_, kPayloadSizes[kNumPayloadSizes - 1] +
|
2015-10-02 03:39:33 -07:00
|
|
|
rtp_header_len + kRtxHeaderSize,
|
|
|
|
|
_))
|
2015-09-28 09:59:31 -07:00
|
|
|
.WillOnce(testing::Return(true));
|
2015-10-02 03:39:33 -07:00
|
|
|
EXPECT_CALL(transport, SendRtp(_, kMaxPaddingSize + rtp_header_len, _))
|
2015-09-28 09:59:31 -07:00
|
|
|
.WillOnce(testing::Return(true));
|
2014-07-15 15:25:39 +00:00
|
|
|
EXPECT_EQ(kPayloadSizes[kNumPayloadSizes - 1] + kMaxPaddingSize,
|
2016-06-01 06:31:17 -07:00
|
|
|
rtp_sender_->TimeToSendPadding(999, PacketInfo::kNotAProbe));
|
2013-12-04 10:24:26 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-08 11:44:14 +02:00
|
|
|
TEST_F(RtpSenderTestWithoutPacer, SendGenericVideo) {
|
2013-03-18 16:39:03 +00:00
|
|
|
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
|
|
|
|
|
const uint8_t payload_type = 127;
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000,
|
|
|
|
|
0, 1500));
|
|
|
|
|
uint8_t payload[] = {47, 11, 32, 93, 89};
|
|
|
|
|
|
|
|
|
|
// Send keyframe
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(kVideoFrameKey, payload_type, 1234,
|
|
|
|
|
4321, payload, sizeof(payload),
|
|
|
|
|
nullptr, nullptr, nullptr));
|
2013-03-18 16:39:03 +00:00
|
|
|
|
2016-11-21 01:35:29 -08:00
|
|
|
auto sent_payload = transport_.last_sent_packet().payload();
|
|
|
|
|
uint8_t generic_header = sent_payload[0];
|
2013-03-18 16:39:03 +00:00
|
|
|
EXPECT_TRUE(generic_header & RtpFormatVideoGeneric::kKeyFrameBit);
|
|
|
|
|
EXPECT_TRUE(generic_header & RtpFormatVideoGeneric::kFirstPacketBit);
|
2016-11-21 01:35:29 -08:00
|
|
|
EXPECT_THAT(sent_payload.subview(1), ElementsAreArray(payload));
|
2013-03-18 16:39:03 +00:00
|
|
|
|
|
|
|
|
// Send delta frame
|
|
|
|
|
payload[0] = 13;
|
|
|
|
|
payload[1] = 42;
|
|
|
|
|
payload[4] = 13;
|
|
|
|
|
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
|
|
|
|
kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
|
|
|
|
|
nullptr, nullptr, nullptr));
|
2013-03-18 16:39:03 +00:00
|
|
|
|
2016-11-21 01:35:29 -08:00
|
|
|
sent_payload = transport_.last_sent_packet().payload();
|
|
|
|
|
generic_header = sent_payload[0];
|
2013-03-18 16:39:03 +00:00
|
|
|
EXPECT_FALSE(generic_header & RtpFormatVideoGeneric::kKeyFrameBit);
|
|
|
|
|
EXPECT_TRUE(generic_header & RtpFormatVideoGeneric::kFirstPacketBit);
|
2016-11-21 01:35:29 -08:00
|
|
|
EXPECT_THAT(sent_payload.subview(1), ElementsAreArray(payload));
|
2013-03-18 16:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
2016-11-10 05:04:48 -08:00
|
|
|
TEST_F(RtpSenderTest, SendFlexfecPackets) {
|
|
|
|
|
constexpr int kMediaPayloadType = 127;
|
|
|
|
|
constexpr int kFlexfecPayloadType = 118;
|
|
|
|
|
constexpr uint32_t kMediaSsrc = 1234;
|
|
|
|
|
constexpr uint32_t kFlexfecSsrc = 5678;
|
|
|
|
|
const std::vector<RtpExtension> kNoRtpExtensions;
|
|
|
|
|
FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc,
|
|
|
|
|
kNoRtpExtensions, &fake_clock_);
|
|
|
|
|
|
|
|
|
|
// Reset |rtp_sender_| to use FlexFEC.
|
2016-11-17 01:38:43 -08:00
|
|
|
rtp_sender_.reset(new RTPSender(
|
|
|
|
|
false, &fake_clock_, &transport_, &mock_paced_sender_, &flexfec_sender,
|
|
|
|
|
&seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
|
|
|
|
|
&mock_rtc_event_log_, &send_packet_observer_,
|
|
|
|
|
&retransmission_rate_limiter_, nullptr));
|
2016-11-10 05:04:48 -08:00
|
|
|
rtp_sender_->SetSSRC(kMediaSsrc);
|
|
|
|
|
rtp_sender_->SetSequenceNumber(kSeqNum);
|
|
|
|
|
rtp_sender_->SetSendPayloadType(kMediaPayloadType);
|
|
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 10);
|
|
|
|
|
|
|
|
|
|
// Parameters selected to generate a single FEC packet per media packet.
|
|
|
|
|
FecProtectionParams params;
|
|
|
|
|
params.fec_rate = 15;
|
|
|
|
|
params.max_fec_frames = 1;
|
|
|
|
|
params.fec_mask_type = kFecMaskRandom;
|
|
|
|
|
rtp_sender_->SetFecParameters(params, params);
|
|
|
|
|
|
2016-11-14 05:14:50 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_,
|
|
|
|
|
InsertPacket(RtpPacketSender::kLowPriority, kMediaSsrc, kSeqNum,
|
|
|
|
|
_, _, false));
|
|
|
|
|
uint16_t flexfec_seq_num;
|
2016-11-10 05:04:48 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kLowPriority,
|
2016-11-14 05:14:50 -08:00
|
|
|
kFlexfecSsrc, _, _, _, false))
|
|
|
|
|
.WillOnce(testing::SaveArg<2>(&flexfec_seq_num));
|
2016-11-10 05:04:48 -08:00
|
|
|
SendGenericPayload();
|
|
|
|
|
EXPECT_CALL(mock_rtc_event_log_,
|
|
|
|
|
LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _))
|
2016-11-14 05:14:50 -08:00
|
|
|
.Times(2);
|
2016-11-10 05:04:48 -08:00
|
|
|
EXPECT_TRUE(rtp_sender_->TimeToSendPacket(
|
2016-11-14 05:14:50 -08:00
|
|
|
kMediaSsrc, kSeqNum, fake_clock_.TimeInMilliseconds(), false, 0));
|
|
|
|
|
EXPECT_TRUE(rtp_sender_->TimeToSendPacket(kFlexfecSsrc, flexfec_seq_num,
|
|
|
|
|
fake_clock_.TimeInMilliseconds(),
|
|
|
|
|
false, 0));
|
|
|
|
|
ASSERT_EQ(2, transport_.packets_sent());
|
2016-11-10 05:04:48 -08:00
|
|
|
const RtpPacketReceived& media_packet = transport_.sent_packets_[0];
|
|
|
|
|
EXPECT_EQ(kMediaPayloadType, media_packet.PayloadType());
|
2016-11-14 05:14:50 -08:00
|
|
|
EXPECT_EQ(kSeqNum, media_packet.SequenceNumber());
|
2016-11-10 05:04:48 -08:00
|
|
|
EXPECT_EQ(kMediaSsrc, media_packet.Ssrc());
|
2016-11-14 05:14:50 -08:00
|
|
|
const RtpPacketReceived& flexfec_packet = transport_.sent_packets_[1];
|
|
|
|
|
EXPECT_EQ(kFlexfecPayloadType, flexfec_packet.PayloadType());
|
|
|
|
|
EXPECT_EQ(flexfec_seq_num, flexfec_packet.SequenceNumber());
|
|
|
|
|
EXPECT_EQ(kFlexfecSsrc, flexfec_packet.Ssrc());
|
2016-11-10 05:04:48 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTestWithoutPacer, SendFlexfecPackets) {
|
|
|
|
|
constexpr int kMediaPayloadType = 127;
|
|
|
|
|
constexpr int kFlexfecPayloadType = 118;
|
|
|
|
|
constexpr uint32_t kMediaSsrc = 1234;
|
|
|
|
|
constexpr uint32_t kFlexfecSsrc = 5678;
|
|
|
|
|
const std::vector<RtpExtension> kNoRtpExtensions;
|
|
|
|
|
FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc,
|
|
|
|
|
kNoRtpExtensions, &fake_clock_);
|
|
|
|
|
|
|
|
|
|
// Reset |rtp_sender_| to use FlexFEC.
|
|
|
|
|
rtp_sender_.reset(new RTPSender(false, &fake_clock_, &transport_, nullptr,
|
|
|
|
|
&flexfec_sender, &seq_num_allocator_, nullptr,
|
|
|
|
|
nullptr, nullptr, nullptr,
|
|
|
|
|
&mock_rtc_event_log_, &send_packet_observer_,
|
2016-11-17 01:38:43 -08:00
|
|
|
&retransmission_rate_limiter_, nullptr));
|
2016-11-10 05:04:48 -08:00
|
|
|
rtp_sender_->SetSSRC(kMediaSsrc);
|
|
|
|
|
rtp_sender_->SetSequenceNumber(kSeqNum);
|
|
|
|
|
rtp_sender_->SetSendPayloadType(kMediaPayloadType);
|
|
|
|
|
|
|
|
|
|
// Parameters selected to generate a single FEC packet per media packet.
|
|
|
|
|
FecProtectionParams params;
|
|
|
|
|
params.fec_rate = 15;
|
|
|
|
|
params.max_fec_frames = 1;
|
|
|
|
|
params.fec_mask_type = kFecMaskRandom;
|
|
|
|
|
rtp_sender_->SetFecParameters(params, params);
|
|
|
|
|
|
|
|
|
|
EXPECT_CALL(mock_rtc_event_log_,
|
|
|
|
|
LogRtpHeader(PacketDirection::kOutgoingPacket, _, _, _))
|
|
|
|
|
.Times(2);
|
|
|
|
|
SendGenericPayload();
|
|
|
|
|
ASSERT_EQ(2, transport_.packets_sent());
|
|
|
|
|
const RtpPacketReceived& media_packet = transport_.sent_packets_[0];
|
|
|
|
|
EXPECT_EQ(kMediaPayloadType, media_packet.PayloadType());
|
|
|
|
|
EXPECT_EQ(kMediaSsrc, media_packet.Ssrc());
|
|
|
|
|
const RtpPacketReceived& flexfec_packet = transport_.sent_packets_[1];
|
|
|
|
|
EXPECT_EQ(kFlexfecPayloadType, flexfec_packet.PayloadType());
|
|
|
|
|
EXPECT_EQ(kFlexfecSsrc, flexfec_packet.Ssrc());
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-04 15:09:27 +00:00
|
|
|
TEST_F(RtpSenderTest, FrameCountCallbacks) {
|
|
|
|
|
class TestCallback : public FrameCountObserver {
|
|
|
|
|
public:
|
2014-12-18 13:50:16 +00:00
|
|
|
TestCallback() : FrameCountObserver(), num_calls_(0), ssrc_(0) {}
|
2013-12-04 15:09:27 +00:00
|
|
|
virtual ~TestCallback() {}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void FrameCountUpdated(const FrameCounts& frame_counts,
|
|
|
|
|
uint32_t ssrc) override {
|
2013-12-04 15:09:27 +00:00
|
|
|
++num_calls_;
|
|
|
|
|
ssrc_ = ssrc;
|
2014-12-18 13:50:16 +00:00
|
|
|
frame_counts_ = frame_counts;
|
2013-12-04 15:09:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t num_calls_;
|
|
|
|
|
uint32_t ssrc_;
|
2014-12-18 13:50:16 +00:00
|
|
|
FrameCounts frame_counts_;
|
2013-12-04 15:09:27 +00:00
|
|
|
} callback;
|
|
|
|
|
|
2016-11-17 01:38:43 -08:00
|
|
|
rtp_sender_.reset(
|
|
|
|
|
new RTPSender(false, &fake_clock_, &transport_, &mock_paced_sender_,
|
|
|
|
|
nullptr, nullptr, nullptr, nullptr, &callback, nullptr,
|
|
|
|
|
nullptr, nullptr, &retransmission_rate_limiter_, nullptr));
|
2014-07-10 09:39:23 +00:00
|
|
|
|
2013-12-04 15:09:27 +00:00
|
|
|
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
|
|
|
|
|
const uint8_t payload_type = 127;
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000,
|
|
|
|
|
0, 1500));
|
|
|
|
|
uint8_t payload[] = {47, 11, 32, 93, 89};
|
|
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 1);
|
|
|
|
|
uint32_t ssrc = rtp_sender_->SSRC();
|
|
|
|
|
|
2016-01-14 14:37:39 -08:00
|
|
|
EXPECT_CALL(mock_paced_sender_, InsertPacket(_, _, _, _, _, _))
|
|
|
|
|
.Times(::testing::AtLeast(2));
|
|
|
|
|
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(kVideoFrameKey, payload_type, 1234,
|
|
|
|
|
4321, payload, sizeof(payload),
|
|
|
|
|
nullptr, nullptr, nullptr));
|
2013-12-04 15:09:27 +00:00
|
|
|
|
|
|
|
|
EXPECT_EQ(1U, callback.num_calls_);
|
|
|
|
|
EXPECT_EQ(ssrc, callback.ssrc_);
|
2014-12-18 13:50:16 +00:00
|
|
|
EXPECT_EQ(1, callback.frame_counts_.key_frames);
|
|
|
|
|
EXPECT_EQ(0, callback.frame_counts_.delta_frames);
|
2013-12-04 15:09:27 +00:00
|
|
|
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
|
|
|
|
kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
|
|
|
|
|
nullptr, nullptr, nullptr));
|
2013-12-04 15:09:27 +00:00
|
|
|
|
|
|
|
|
EXPECT_EQ(2U, callback.num_calls_);
|
|
|
|
|
EXPECT_EQ(ssrc, callback.ssrc_);
|
2014-12-18 13:50:16 +00:00
|
|
|
EXPECT_EQ(1, callback.frame_counts_.key_frames);
|
|
|
|
|
EXPECT_EQ(1, callback.frame_counts_.delta_frames);
|
2013-12-04 15:09:27 +00:00
|
|
|
|
2014-07-10 09:39:23 +00:00
|
|
|
rtp_sender_.reset();
|
2013-12-04 15:09:27 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-13 09:46:59 +00:00
|
|
|
TEST_F(RtpSenderTest, BitrateCallbacks) {
|
|
|
|
|
class TestCallback : public BitrateStatisticsObserver {
|
|
|
|
|
public:
|
2016-07-13 09:11:28 -07:00
|
|
|
TestCallback()
|
|
|
|
|
: BitrateStatisticsObserver(),
|
|
|
|
|
num_calls_(0),
|
|
|
|
|
ssrc_(0),
|
|
|
|
|
total_bitrate_(0),
|
|
|
|
|
retransmit_bitrate_(0) {}
|
2013-12-13 09:46:59 +00:00
|
|
|
virtual ~TestCallback() {}
|
|
|
|
|
|
2016-07-13 09:11:28 -07:00
|
|
|
void Notify(uint32_t total_bitrate,
|
|
|
|
|
uint32_t retransmit_bitrate,
|
2015-03-04 12:58:35 +00:00
|
|
|
uint32_t ssrc) override {
|
2013-12-13 09:46:59 +00:00
|
|
|
++num_calls_;
|
|
|
|
|
ssrc_ = ssrc;
|
2016-07-13 09:11:28 -07:00
|
|
|
total_bitrate_ = total_bitrate;
|
|
|
|
|
retransmit_bitrate_ = retransmit_bitrate;
|
2013-12-13 09:46:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t num_calls_;
|
|
|
|
|
uint32_t ssrc_;
|
2016-07-13 09:11:28 -07:00
|
|
|
uint32_t total_bitrate_;
|
|
|
|
|
uint32_t retransmit_bitrate_;
|
2013-12-13 09:46:59 +00:00
|
|
|
} callback;
|
2016-11-10 05:04:48 -08:00
|
|
|
rtp_sender_.reset(new RTPSender(false, &fake_clock_, &transport_, nullptr,
|
|
|
|
|
nullptr, nullptr, nullptr, &callback, nullptr,
|
|
|
|
|
nullptr, nullptr, nullptr,
|
2016-11-17 01:38:43 -08:00
|
|
|
&retransmission_rate_limiter_, nullptr));
|
2013-12-13 09:46:59 +00:00
|
|
|
|
2016-07-13 09:11:28 -07:00
|
|
|
// Simulate kNumPackets sent with kPacketInterval ms intervals, with the
|
|
|
|
|
// number of packets selected so that we fill (but don't overflow) the one
|
|
|
|
|
// second averaging window.
|
|
|
|
|
const uint32_t kWindowSizeMs = 1000;
|
2013-12-13 09:46:59 +00:00
|
|
|
const uint32_t kPacketInterval = 20;
|
2016-07-13 09:11:28 -07:00
|
|
|
const uint32_t kNumPackets =
|
|
|
|
|
(kWindowSizeMs - kPacketInterval) / kPacketInterval;
|
2013-12-13 09:46:59 +00:00
|
|
|
// Overhead = 12 bytes RTP header + 1 byte generic header.
|
|
|
|
|
const uint32_t kPacketOverhead = 13;
|
|
|
|
|
|
|
|
|
|
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
|
|
|
|
|
const uint8_t payload_type = 127;
|
2015-12-10 02:39:40 -08:00
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000,
|
|
|
|
|
0, 1500));
|
2013-12-13 09:46:59 +00:00
|
|
|
uint8_t payload[] = {47, 11, 32, 93, 89};
|
|
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 1);
|
|
|
|
|
uint32_t ssrc = rtp_sender_->SSRC();
|
|
|
|
|
|
|
|
|
|
// Initial process call so we get a new time window.
|
|
|
|
|
rtp_sender_->ProcessBitrate();
|
|
|
|
|
|
|
|
|
|
// Send a few frames.
|
|
|
|
|
for (uint32_t i = 0; i < kNumPackets; ++i) {
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
|
|
|
|
kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
|
|
|
|
|
nullptr, nullptr, nullptr));
|
2013-12-13 09:46:59 +00:00
|
|
|
fake_clock_.AdvanceTimeMilliseconds(kPacketInterval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtp_sender_->ProcessBitrate();
|
|
|
|
|
|
2014-11-05 14:05:29 +00:00
|
|
|
// We get one call for every stats updated, thus two calls since both the
|
|
|
|
|
// stream stats and the retransmit stats are updated once.
|
|
|
|
|
EXPECT_EQ(2u, callback.num_calls_);
|
2013-12-13 09:46:59 +00:00
|
|
|
EXPECT_EQ(ssrc, callback.ssrc_);
|
2016-07-13 09:11:28 -07:00
|
|
|
const uint32_t kTotalPacketSize = kPacketOverhead + sizeof(payload);
|
|
|
|
|
// Bitrate measured over delta between last and first timestamp, plus one.
|
|
|
|
|
const uint32_t kExpectedWindowMs = kNumPackets * kPacketInterval + 1;
|
|
|
|
|
const uint32_t kExpectedBitsAccumulated = kTotalPacketSize * kNumPackets * 8;
|
|
|
|
|
const uint32_t kExpectedRateBps =
|
|
|
|
|
(kExpectedBitsAccumulated * 1000 + (kExpectedWindowMs / 2)) /
|
|
|
|
|
kExpectedWindowMs;
|
|
|
|
|
EXPECT_EQ(kExpectedRateBps, callback.total_bitrate_);
|
2013-12-13 09:46:59 +00:00
|
|
|
|
2014-07-08 14:32:58 +00:00
|
|
|
rtp_sender_.reset();
|
2013-12-13 09:46:59 +00:00
|
|
|
}
|
|
|
|
|
|
2013-05-20 20:55:07 +00:00
|
|
|
class RtpSenderAudioTest : public RtpSenderTest {
|
|
|
|
|
protected:
|
|
|
|
|
RtpSenderAudioTest() {}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void SetUp() override {
|
2013-05-20 20:55:07 +00:00
|
|
|
payload_ = kAudioPayload;
|
2016-11-10 05:04:48 -08:00
|
|
|
rtp_sender_.reset(new RTPSender(true, &fake_clock_, &transport_, nullptr,
|
|
|
|
|
nullptr, nullptr, nullptr, nullptr, nullptr,
|
|
|
|
|
nullptr, nullptr, nullptr,
|
2016-11-17 01:38:43 -08:00
|
|
|
&retransmission_rate_limiter_, nullptr));
|
2013-05-20 20:55:07 +00:00
|
|
|
rtp_sender_->SetSequenceNumber(kSeqNum);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-10-08 11:44:14 +02:00
|
|
|
TEST_F(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) {
|
2013-12-05 14:29:02 +00:00
|
|
|
class TestCallback : public StreamDataCountersCallback {
|
|
|
|
|
public:
|
2015-12-10 02:39:40 -08:00
|
|
|
TestCallback() : StreamDataCountersCallback(), ssrc_(0), counters_() {}
|
2013-12-05 14:29:02 +00:00
|
|
|
virtual ~TestCallback() {}
|
|
|
|
|
|
2015-03-04 12:58:35 +00:00
|
|
|
void DataCountersUpdated(const StreamDataCounters& counters,
|
|
|
|
|
uint32_t ssrc) override {
|
2013-12-05 14:29:02 +00:00
|
|
|
ssrc_ = ssrc;
|
|
|
|
|
counters_ = counters;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t ssrc_;
|
|
|
|
|
StreamDataCounters counters_;
|
2015-02-04 08:34:47 +00:00
|
|
|
|
|
|
|
|
void MatchPacketCounter(const RtpPacketCounter& expected,
|
|
|
|
|
const RtpPacketCounter& actual) {
|
|
|
|
|
EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
|
|
|
|
|
EXPECT_EQ(expected.header_bytes, actual.header_bytes);
|
|
|
|
|
EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
|
|
|
|
|
EXPECT_EQ(expected.packets, actual.packets);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-09 09:47:53 +00:00
|
|
|
void Matches(uint32_t ssrc, const StreamDataCounters& counters) {
|
|
|
|
|
EXPECT_EQ(ssrc, ssrc_);
|
2015-02-04 08:34:47 +00:00
|
|
|
MatchPacketCounter(counters.transmitted, counters_.transmitted);
|
|
|
|
|
MatchPacketCounter(counters.retransmitted, counters_.retransmitted);
|
2015-01-22 09:39:59 +00:00
|
|
|
EXPECT_EQ(counters.fec.packets, counters_.fec.packets);
|
2013-12-05 14:29:02 +00:00
|
|
|
}
|
|
|
|
|
} callback;
|
|
|
|
|
|
|
|
|
|
const uint8_t kRedPayloadType = 96;
|
|
|
|
|
const uint8_t kUlpfecPayloadType = 97;
|
|
|
|
|
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
|
|
|
|
|
const uint8_t payload_type = 127;
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000,
|
|
|
|
|
0, 1500));
|
|
|
|
|
uint8_t payload[] = {47, 11, 32, 93, 89};
|
|
|
|
|
rtp_sender_->SetStorePacketsStatus(true, 1);
|
|
|
|
|
uint32_t ssrc = rtp_sender_->SSRC();
|
|
|
|
|
|
|
|
|
|
rtp_sender_->RegisterRtpStatisticsCallback(&callback);
|
|
|
|
|
|
|
|
|
|
// Send a frame.
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
|
|
|
|
kVideoFrameKey, payload_type, 1234, 4321, payload,
|
|
|
|
|
sizeof(payload), nullptr, nullptr, nullptr));
|
2014-12-09 09:47:53 +00:00
|
|
|
StreamDataCounters expected;
|
2015-01-22 09:39:59 +00:00
|
|
|
expected.transmitted.payload_bytes = 6;
|
|
|
|
|
expected.transmitted.header_bytes = 12;
|
|
|
|
|
expected.transmitted.padding_bytes = 0;
|
|
|
|
|
expected.transmitted.packets = 1;
|
|
|
|
|
expected.retransmitted.payload_bytes = 0;
|
|
|
|
|
expected.retransmitted.header_bytes = 0;
|
|
|
|
|
expected.retransmitted.padding_bytes = 0;
|
|
|
|
|
expected.retransmitted.packets = 0;
|
|
|
|
|
expected.fec.packets = 0;
|
2014-12-09 09:47:53 +00:00
|
|
|
callback.Matches(ssrc, expected);
|
2013-12-05 14:29:02 +00:00
|
|
|
|
|
|
|
|
// Retransmit a frame.
|
|
|
|
|
uint16_t seqno = rtp_sender_->SequenceNumber() - 1;
|
|
|
|
|
rtp_sender_->ReSendPacket(seqno, 0);
|
2015-01-22 09:39:59 +00:00
|
|
|
expected.transmitted.payload_bytes = 12;
|
|
|
|
|
expected.transmitted.header_bytes = 24;
|
|
|
|
|
expected.transmitted.packets = 2;
|
|
|
|
|
expected.retransmitted.payload_bytes = 6;
|
|
|
|
|
expected.retransmitted.header_bytes = 12;
|
|
|
|
|
expected.retransmitted.padding_bytes = 0;
|
|
|
|
|
expected.retransmitted.packets = 1;
|
2014-12-09 09:47:53 +00:00
|
|
|
callback.Matches(ssrc, expected);
|
2013-12-05 14:29:02 +00:00
|
|
|
|
|
|
|
|
// Send padding.
|
2016-06-01 06:31:17 -07:00
|
|
|
rtp_sender_->TimeToSendPadding(kMaxPaddingSize, PacketInfo::kNotAProbe);
|
2015-01-22 09:39:59 +00:00
|
|
|
expected.transmitted.payload_bytes = 12;
|
|
|
|
|
expected.transmitted.header_bytes = 36;
|
|
|
|
|
expected.transmitted.padding_bytes = kMaxPaddingSize;
|
|
|
|
|
expected.transmitted.packets = 3;
|
2014-12-09 09:47:53 +00:00
|
|
|
callback.Matches(ssrc, expected);
|
2013-12-05 14:29:02 +00:00
|
|
|
|
2016-11-07 03:05:06 -08:00
|
|
|
// Send ULPFEC.
|
|
|
|
|
rtp_sender_->SetUlpfecConfig(kRedPayloadType, kUlpfecPayloadType);
|
2013-12-05 14:29:02 +00:00
|
|
|
FecProtectionParams fec_params;
|
|
|
|
|
fec_params.fec_mask_type = kFecMaskRandom;
|
|
|
|
|
fec_params.fec_rate = 1;
|
|
|
|
|
fec_params.max_fec_frames = 1;
|
2016-11-07 03:36:05 -08:00
|
|
|
rtp_sender_->SetFecParameters(fec_params, fec_params);
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
|
|
|
|
kVideoFrameDelta, payload_type, 1234, 4321, payload,
|
|
|
|
|
sizeof(payload), nullptr, nullptr, nullptr));
|
2015-01-22 09:39:59 +00:00
|
|
|
expected.transmitted.payload_bytes = 40;
|
|
|
|
|
expected.transmitted.header_bytes = 60;
|
|
|
|
|
expected.transmitted.packets = 5;
|
|
|
|
|
expected.fec.packets = 1;
|
2014-12-09 09:47:53 +00:00
|
|
|
callback.Matches(ssrc, expected);
|
2013-12-05 14:29:02 +00:00
|
|
|
|
2015-08-03 04:38:41 -07:00
|
|
|
rtp_sender_->RegisterRtpStatisticsCallback(nullptr);
|
2013-12-05 14:29:02 +00:00
|
|
|
}
|
|
|
|
|
|
2013-05-20 20:55:07 +00:00
|
|
|
TEST_F(RtpSenderAudioTest, SendAudio) {
|
|
|
|
|
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "PAYLOAD_NAME";
|
|
|
|
|
const uint8_t payload_type = 127;
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 48000,
|
|
|
|
|
0, 1500));
|
|
|
|
|
uint8_t payload[] = {47, 11, 32, 93, 89};
|
|
|
|
|
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
|
|
|
|
kAudioFrameCN, payload_type, 1234, 4321, payload,
|
|
|
|
|
sizeof(payload), nullptr, nullptr, nullptr));
|
2013-05-20 20:55:07 +00:00
|
|
|
|
2016-11-21 01:35:29 -08:00
|
|
|
auto sent_payload = transport_.last_sent_packet().payload();
|
|
|
|
|
EXPECT_THAT(sent_payload, ElementsAreArray(payload));
|
2013-05-20 20:55:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) {
|
|
|
|
|
EXPECT_EQ(0, rtp_sender_->SetAudioLevel(kAudioLevel));
|
2015-12-10 02:39:40 -08:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
|
|
|
|
|
kAudioLevelExtensionId));
|
2013-05-20 20:55:07 +00:00
|
|
|
|
|
|
|
|
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "PAYLOAD_NAME";
|
|
|
|
|
const uint8_t payload_type = 127;
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 48000,
|
|
|
|
|
0, 1500));
|
|
|
|
|
uint8_t payload[] = {47, 11, 32, 93, 89};
|
|
|
|
|
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
|
|
|
|
kAudioFrameCN, payload_type, 1234, 4321, payload,
|
|
|
|
|
sizeof(payload), nullptr, nullptr, nullptr));
|
2013-05-20 20:55:07 +00:00
|
|
|
|
2016-11-21 01:35:29 -08:00
|
|
|
auto sent_payload = transport_.last_sent_packet().payload();
|
|
|
|
|
EXPECT_THAT(sent_payload, ElementsAreArray(payload));
|
2016-10-26 02:41:55 -07:00
|
|
|
// Verify AudioLevel extension.
|
|
|
|
|
bool voice_activity;
|
|
|
|
|
uint8_t audio_level;
|
|
|
|
|
EXPECT_TRUE(transport_.last_sent_packet().GetExtension<AudioLevel>(
|
|
|
|
|
&voice_activity, &audio_level));
|
|
|
|
|
EXPECT_EQ(kAudioLevel, audio_level);
|
|
|
|
|
EXPECT_FALSE(voice_activity);
|
2013-05-20 20:55:07 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-03 11:46:54 +00:00
|
|
|
// As RFC4733, named telephone events are carried as part of the audio stream
|
|
|
|
|
// and must use the same sequence number and timestamp base as the regular
|
|
|
|
|
// audio channel.
|
|
|
|
|
// This test checks the marker bit for the first packet and the consequent
|
|
|
|
|
// packets of the same telephone event. Since it is specifically for DTMF
|
2015-10-19 02:39:06 -07:00
|
|
|
// events, ignoring audio packets and sending kEmptyFrame instead of those.
|
2014-09-03 11:46:54 +00:00
|
|
|
TEST_F(RtpSenderAudioTest, CheckMarkerBitForTelephoneEvents) {
|
2016-11-17 05:25:37 -08:00
|
|
|
const char* kDtmfPayloadName = "telephone-event";
|
|
|
|
|
const uint32_t kPayloadFrequency = 8000;
|
|
|
|
|
const uint8_t kPayloadType = 126;
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(kDtmfPayloadName, kPayloadType,
|
|
|
|
|
kPayloadFrequency, 0, 0));
|
2014-09-03 11:46:54 +00:00
|
|
|
// For Telephone events, payload is not added to the registered payload list,
|
|
|
|
|
// it will register only the payload used for audio stream.
|
|
|
|
|
// Registering the payload again for audio stream with different payload name.
|
2016-11-17 05:25:37 -08:00
|
|
|
const char* kPayloadName = "payload_name";
|
|
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(kPayloadName, kPayloadType,
|
|
|
|
|
kPayloadFrequency, 1, 0));
|
2014-09-03 11:46:54 +00:00
|
|
|
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
|
|
|
|
|
// DTMF event key=9, duration=500 and attenuationdB=10
|
|
|
|
|
rtp_sender_->SendTelephoneEvent(9, 500, 10);
|
|
|
|
|
// During start, it takes the starting timestamp as last sent timestamp.
|
|
|
|
|
// The duration is calculated as the difference of current and last sent
|
|
|
|
|
// timestamp. So for first call it will skip since the duration is zero.
|
2016-11-17 05:25:37 -08:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(kEmptyFrame, kPayloadType,
|
|
|
|
|
capture_time_ms, 0, nullptr, 0,
|
|
|
|
|
nullptr, nullptr, nullptr));
|
2014-09-03 11:46:54 +00:00
|
|
|
// DTMF Sample Length is (Frequency/1000) * Duration.
|
|
|
|
|
// So in this case, it is (8000/1000) * 500 = 4000.
|
|
|
|
|
// Sending it as two packets.
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
2016-11-17 05:25:37 -08:00
|
|
|
kEmptyFrame, kPayloadType, capture_time_ms + 2000, 0,
|
2016-08-02 17:46:41 -07:00
|
|
|
nullptr, 0, nullptr, nullptr, nullptr));
|
2016-10-26 02:41:55 -07:00
|
|
|
|
2014-09-03 11:46:54 +00:00
|
|
|
// Marker Bit should be set to 1 for first packet.
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_TRUE(transport_.last_sent_packet().Marker());
|
2014-09-03 11:46:54 +00:00
|
|
|
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
2016-11-17 05:25:37 -08:00
|
|
|
kEmptyFrame, kPayloadType, capture_time_ms + 4000, 0,
|
2016-08-02 17:46:41 -07:00
|
|
|
nullptr, 0, nullptr, nullptr, nullptr));
|
2014-09-03 11:46:54 +00:00
|
|
|
// Marker Bit should be set to 0 for rest of the packets.
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_FALSE(transport_.last_sent_packet().Marker());
|
2014-09-03 11:46:54 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-08 11:44:14 +02:00
|
|
|
TEST_F(RtpSenderTestWithoutPacer, BytesReportedCorrectly) {
|
2014-07-10 16:24:54 +00:00
|
|
|
const char* kPayloadName = "GENERIC";
|
|
|
|
|
const uint8_t kPayloadType = 127;
|
|
|
|
|
rtp_sender_->SetSSRC(1234);
|
|
|
|
|
rtp_sender_->SetRtxSsrc(4321);
|
2015-04-21 20:24:50 +08:00
|
|
|
rtp_sender_->SetRtxPayloadType(kPayloadType - 1, kPayloadType);
|
2015-01-13 14:15:15 +00:00
|
|
|
rtp_sender_->SetRtxStatus(kRtxRetransmitted | kRtxRedundantPayloads);
|
2014-07-10 16:24:54 +00:00
|
|
|
|
2015-12-10 02:39:40 -08:00
|
|
|
ASSERT_EQ(0, rtp_sender_->RegisterPayload(kPayloadName, kPayloadType, 90000,
|
|
|
|
|
0, 1500));
|
2014-07-10 16:24:54 +00:00
|
|
|
uint8_t payload[] = {47, 11, 32, 93, 89};
|
|
|
|
|
|
2016-08-02 17:46:41 -07:00
|
|
|
ASSERT_TRUE(rtp_sender_->SendOutgoingData(
|
|
|
|
|
kVideoFrameKey, kPayloadType, 1234, 4321, payload,
|
|
|
|
|
sizeof(payload), nullptr, nullptr, nullptr));
|
2014-07-10 16:24:54 +00:00
|
|
|
|
2014-07-15 15:25:39 +00:00
|
|
|
// Will send 2 full-size padding packets.
|
2016-06-01 06:31:17 -07:00
|
|
|
rtp_sender_->TimeToSendPadding(1, PacketInfo::kNotAProbe);
|
|
|
|
|
rtp_sender_->TimeToSendPadding(1, PacketInfo::kNotAProbe);
|
2014-07-15 15:25:39 +00:00
|
|
|
|
|
|
|
|
StreamDataCounters rtp_stats;
|
|
|
|
|
StreamDataCounters rtx_stats;
|
|
|
|
|
rtp_sender_->GetDataCounters(&rtp_stats, &rtx_stats);
|
|
|
|
|
|
|
|
|
|
// Payload + 1-byte generic header.
|
2014-12-16 12:03:11 +00:00
|
|
|
EXPECT_GT(rtp_stats.first_packet_time_ms, -1);
|
2015-01-22 09:39:59 +00:00
|
|
|
EXPECT_EQ(rtp_stats.transmitted.payload_bytes, sizeof(payload) + 1);
|
|
|
|
|
EXPECT_EQ(rtp_stats.transmitted.header_bytes, 12u);
|
|
|
|
|
EXPECT_EQ(rtp_stats.transmitted.padding_bytes, 0u);
|
|
|
|
|
EXPECT_EQ(rtx_stats.transmitted.payload_bytes, 0u);
|
|
|
|
|
EXPECT_EQ(rtx_stats.transmitted.header_bytes, 24u);
|
|
|
|
|
EXPECT_EQ(rtx_stats.transmitted.padding_bytes, 2 * kMaxPaddingSize);
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(rtp_stats.transmitted.TotalBytes(),
|
2015-12-10 02:39:40 -08:00
|
|
|
rtp_stats.transmitted.payload_bytes +
|
|
|
|
|
rtp_stats.transmitted.header_bytes +
|
|
|
|
|
rtp_stats.transmitted.padding_bytes);
|
2015-01-22 09:39:59 +00:00
|
|
|
EXPECT_EQ(rtx_stats.transmitted.TotalBytes(),
|
2015-12-10 02:39:40 -08:00
|
|
|
rtx_stats.transmitted.payload_bytes +
|
|
|
|
|
rtx_stats.transmitted.header_bytes +
|
|
|
|
|
rtx_stats.transmitted.padding_bytes);
|
2014-12-09 09:47:53 +00:00
|
|
|
|
2015-12-10 02:39:40 -08:00
|
|
|
EXPECT_EQ(
|
|
|
|
|
transport_.total_bytes_sent_,
|
|
|
|
|
rtp_stats.transmitted.TotalBytes() + rtx_stats.transmitted.TotalBytes());
|
2014-07-10 16:24:54 +00:00
|
|
|
}
|
2015-03-04 22:55:15 +00:00
|
|
|
|
2015-10-08 11:44:14 +02:00
|
|
|
TEST_F(RtpSenderTestWithoutPacer, RespectsNackBitrateLimit) {
|
2015-09-29 09:48:22 -07:00
|
|
|
const int32_t kPacketSize = 1400;
|
|
|
|
|
const int32_t kNumPackets = 30;
|
|
|
|
|
|
2016-07-13 09:11:28 -07:00
|
|
|
retransmission_rate_limiter_.SetMaxRate(kPacketSize * kNumPackets * 8);
|
|
|
|
|
|
2015-09-29 09:48:22 -07:00
|
|
|
rtp_sender_->SetStorePacketsStatus(true, kNumPackets);
|
|
|
|
|
const uint16_t kStartSequenceNumber = rtp_sender_->SequenceNumber();
|
2016-08-26 18:48:46 +02:00
|
|
|
std::vector<uint16_t> sequence_numbers;
|
2015-09-29 09:48:22 -07:00
|
|
|
for (int32_t i = 0; i < kNumPackets; ++i) {
|
|
|
|
|
sequence_numbers.push_back(kStartSequenceNumber + i);
|
|
|
|
|
fake_clock_.AdvanceTimeMilliseconds(1);
|
|
|
|
|
SendPacket(fake_clock_.TimeInMilliseconds(), kPacketSize);
|
|
|
|
|
}
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(kNumPackets, transport_.packets_sent());
|
2015-09-29 09:48:22 -07:00
|
|
|
|
|
|
|
|
fake_clock_.AdvanceTimeMilliseconds(1000 - kNumPackets);
|
|
|
|
|
|
|
|
|
|
// Resending should work - brings the bandwidth up to the limit.
|
|
|
|
|
// NACK bitrate is capped to the same bitrate as the encoder, since the max
|
|
|
|
|
// protection overhead is 50% (see MediaOptimization::SetTargetRates).
|
2016-08-26 18:48:46 +02:00
|
|
|
rtp_sender_->OnReceivedNack(sequence_numbers, 0);
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(kNumPackets * 2, transport_.packets_sent());
|
2015-09-29 09:48:22 -07:00
|
|
|
|
2016-07-13 09:11:28 -07:00
|
|
|
// Must be at least 5ms in between retransmission attempts.
|
|
|
|
|
fake_clock_.AdvanceTimeMilliseconds(5);
|
|
|
|
|
|
2015-09-29 09:48:22 -07:00
|
|
|
// Resending should not work, bandwidth exceeded.
|
2016-08-26 18:48:46 +02:00
|
|
|
rtp_sender_->OnReceivedNack(sequence_numbers, 0);
|
2016-10-26 02:41:55 -07:00
|
|
|
EXPECT_EQ(kNumPackets * 2, transport_.packets_sent());
|
2015-09-29 09:48:22 -07:00
|
|
|
}
|
|
|
|
|
|
2016-10-26 03:33:11 -07:00
|
|
|
TEST_F(RtpSenderVideoTest, KeyFrameHasCVO) {
|
2016-10-19 06:11:39 -07:00
|
|
|
uint8_t kFrame[kMaxPacketLength];
|
2015-03-04 22:55:15 +00:00
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
|
|
|
|
|
2016-10-26 03:33:11 -07:00
|
|
|
RTPVideoHeader hdr = {0};
|
|
|
|
|
hdr.rotation = kVideoRotation_0;
|
2015-03-04 22:55:15 +00:00
|
|
|
rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, kPayload,
|
2016-10-19 06:11:39 -07:00
|
|
|
kTimestamp, 0, kFrame, sizeof(kFrame), nullptr,
|
2015-04-14 21:28:08 +02:00
|
|
|
&hdr);
|
2015-03-04 22:55:15 +00:00
|
|
|
|
2016-10-26 03:33:11 -07:00
|
|
|
VideoRotation rotation;
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
|
transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_0, rotation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderVideoTest, DeltaFrameHasCVOWhenChanged) {
|
|
|
|
|
uint8_t kFrame[kMaxPacketLength];
|
|
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
|
|
|
|
|
|
|
|
|
RTPVideoHeader hdr = {0};
|
|
|
|
|
hdr.rotation = kVideoRotation_90;
|
|
|
|
|
EXPECT_TRUE(rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey,
|
|
|
|
|
kPayload, kTimestamp, 0, kFrame,
|
|
|
|
|
sizeof(kFrame), nullptr, &hdr));
|
|
|
|
|
|
|
|
|
|
hdr.rotation = kVideoRotation_0;
|
|
|
|
|
EXPECT_TRUE(rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameDelta,
|
|
|
|
|
kPayload, kTimestamp + 1, 0, kFrame,
|
|
|
|
|
sizeof(kFrame), nullptr, &hdr));
|
|
|
|
|
|
|
|
|
|
VideoRotation rotation;
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
|
transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_0, rotation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderVideoTest, DeltaFrameHasCVOWhenNonZero) {
|
|
|
|
|
uint8_t kFrame[kMaxPacketLength];
|
|
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
2015-03-04 22:55:15 +00:00
|
|
|
|
2016-10-26 03:33:11 -07:00
|
|
|
RTPVideoHeader hdr = {0};
|
|
|
|
|
hdr.rotation = kVideoRotation_90;
|
|
|
|
|
EXPECT_TRUE(rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey,
|
|
|
|
|
kPayload, kTimestamp, 0, kFrame,
|
|
|
|
|
sizeof(kFrame), nullptr, &hdr));
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameDelta,
|
|
|
|
|
kPayload, kTimestamp + 1, 0, kFrame,
|
|
|
|
|
sizeof(kFrame), nullptr, &hdr));
|
|
|
|
|
|
|
|
|
|
VideoRotation rotation;
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
|
transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_90, rotation);
|
2015-03-04 22:55:15 +00:00
|
|
|
}
|
2016-09-08 03:24:58 -07:00
|
|
|
|
|
|
|
|
// Make sure rotation is parsed correctly when the Camera (C) and Flip (F) bits
|
|
|
|
|
// are set in the CVO byte.
|
|
|
|
|
TEST_F(RtpSenderVideoTest, SendVideoWithCameraAndFlipCVO) {
|
|
|
|
|
// Test extracting rotation when Camera (C) and Flip (F) bits are zero.
|
|
|
|
|
EXPECT_EQ(kVideoRotation_0, ConvertCVOByteToVideoRotation(0));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_90, ConvertCVOByteToVideoRotation(1));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_180, ConvertCVOByteToVideoRotation(2));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_270, ConvertCVOByteToVideoRotation(3));
|
|
|
|
|
// Test extracting rotation when Camera (C) and Flip (F) bits are set.
|
|
|
|
|
const int flip_bit = 1 << 2;
|
|
|
|
|
const int camera_bit = 1 << 3;
|
|
|
|
|
EXPECT_EQ(kVideoRotation_0,
|
|
|
|
|
ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 0));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_90,
|
|
|
|
|
ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 1));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_180,
|
|
|
|
|
ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 2));
|
|
|
|
|
EXPECT_EQ(kVideoRotation_270,
|
|
|
|
|
ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 3));
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-17 01:38:43 -08:00
|
|
|
namespace {
|
|
|
|
|
class MockOverheadObserver : public OverheadObserver {
|
|
|
|
|
public:
|
|
|
|
|
MOCK_METHOD1(OnOverheadChanged, void(size_t overhead_bytes_per_packet));
|
|
|
|
|
};
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTest, OnOverheadChanged) {
|
|
|
|
|
MockOverheadObserver mock_overhead_observer;
|
|
|
|
|
rtp_sender_.reset(
|
|
|
|
|
new RTPSender(false, &fake_clock_, &transport_, nullptr, nullptr, nullptr,
|
|
|
|
|
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
|
|
|
|
&retransmission_rate_limiter_, &mock_overhead_observer));
|
|
|
|
|
|
|
|
|
|
// Transport overhead is set to 28B.
|
|
|
|
|
EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(28)).Times(1);
|
|
|
|
|
rtp_sender_->SetTransportOverhead(28);
|
|
|
|
|
|
|
|
|
|
// RTP overhead is 12B.
|
|
|
|
|
// 28B + 12B = 40B
|
|
|
|
|
EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(40)).Times(1);
|
|
|
|
|
SendGenericPayload();
|
|
|
|
|
|
|
|
|
|
rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
|
|
|
|
|
kTransmissionTimeOffsetExtensionId);
|
|
|
|
|
|
|
|
|
|
// TransmissionTimeOffset extension has a size of 8B.
|
|
|
|
|
// 28B + 12B + 8B = 48B
|
|
|
|
|
EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(48)).Times(1);
|
|
|
|
|
SendGenericPayload();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(RtpSenderTest, DoesNotUpdateOverheadOnEqualSize) {
|
|
|
|
|
MockOverheadObserver mock_overhead_observer;
|
|
|
|
|
rtp_sender_.reset(
|
|
|
|
|
new RTPSender(false, &fake_clock_, &transport_, nullptr, nullptr, nullptr,
|
|
|
|
|
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
|
|
|
|
&retransmission_rate_limiter_, &mock_overhead_observer));
|
|
|
|
|
|
|
|
|
|
EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(_)).Times(1);
|
|
|
|
|
rtp_sender_->SetTransportOverhead(28);
|
|
|
|
|
rtp_sender_->SetTransportOverhead(28);
|
|
|
|
|
|
|
|
|
|
EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(_)).Times(1);
|
|
|
|
|
SendGenericPayload();
|
|
|
|
|
SendGenericPayload();
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-29 02:24:18 -08:00
|
|
|
TEST_F(RtpSenderTest, AddOverheadToTransportFeedbackObserver) {
|
|
|
|
|
constexpr int kTransportOverheadBytesPerPacket = 28;
|
|
|
|
|
constexpr int kRtpOverheadBytesPerPacket = 12 + 8;
|
|
|
|
|
test::ScopedFieldTrials override_field_trials(
|
|
|
|
|
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
|
|
|
|
|
testing::NiceMock<MockOverheadObserver> mock_overhead_observer;
|
|
|
|
|
rtp_sender_.reset(new RTPSender(
|
|
|
|
|
false, &fake_clock_, &transport_, nullptr, nullptr, &seq_num_allocator_,
|
|
|
|
|
&feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
|
|
|
|
|
nullptr, &retransmission_rate_limiter_, &mock_overhead_observer));
|
|
|
|
|
rtp_sender_->SetTransportOverhead(kTransportOverheadBytesPerPacket);
|
|
|
|
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
|
|
|
|
kRtpExtensionTransportSequenceNumber,
|
|
|
|
|
kTransportSequenceNumberExtensionId));
|
|
|
|
|
EXPECT_CALL(seq_num_allocator_, AllocateSequenceNumber())
|
|
|
|
|
.WillOnce(testing::Return(kTransportSequenceNumber));
|
|
|
|
|
EXPECT_CALL(feedback_observer_,
|
|
|
|
|
AddPacket(kTransportSequenceNumber,
|
|
|
|
|
sizeof(kPayloadData) + kGenericHeaderLength +
|
|
|
|
|
kRtpOverheadBytesPerPacket +
|
|
|
|
|
kTransportOverheadBytesPerPacket,
|
|
|
|
|
PacketInfo::kNotAProbe))
|
|
|
|
|
.Times(1);
|
|
|
|
|
EXPECT_CALL(mock_overhead_observer,
|
|
|
|
|
OnOverheadChanged(kTransportOverheadBytesPerPacket +
|
|
|
|
|
kRtpOverheadBytesPerPacket))
|
|
|
|
|
.Times(1);
|
|
|
|
|
SendGenericPayload();
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-20 20:55:07 +00:00
|
|
|
} // namespace webrtc
|