Implement ViE forwarding to RBE of packets for BWE coming in through the ViENetwork::ReceivedBWEPacket API.
BUG= R=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/10429004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5765 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
c693a2a624
commit
3fb8f7bbb0
@ -49,11 +49,6 @@ enum StreamType {
|
|||||||
kViEStreamTypeRtx = 1 // Retransmission media stream
|
kViEStreamTypeRtx = 1 // Retransmission media stream
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BandwidthEstimationMode {
|
|
||||||
kViEMultiStreamEstimation,
|
|
||||||
kViESingleStreamEstimation
|
|
||||||
};
|
|
||||||
|
|
||||||
// This class declares an abstract interface for a user defined observer. It is
|
// This class declares an abstract interface for a user defined observer. It is
|
||||||
// up to the VideoEngine user to implement a derived class which implements the
|
// up to the VideoEngine user to implement a derived class which implements the
|
||||||
// observer class. The observer is registered using RegisterRTPObserver() and
|
// observer class. The observer is registered using RegisterRTPObserver() and
|
||||||
|
214
webrtc/video_engine/test/auto_test/automated/vie_network_test.cc
Normal file
214
webrtc/video_engine/test/auto_test/automated/vie_network_test.cc
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "gflags/gflags.h"
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
||||||
|
#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
|
||||||
|
#include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/sleep.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/tick_util.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class RtcpCollectorTransport : public webrtc::Transport {
|
||||||
|
public:
|
||||||
|
RtcpCollectorTransport() : packets_() {}
|
||||||
|
virtual ~RtcpCollectorTransport() {}
|
||||||
|
|
||||||
|
virtual int SendPacket(int /*channel*/, const void* /*data*/, int /*len*/) {
|
||||||
|
EXPECT_TRUE(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual int SendRTCPPacket(int channel, const void* data, int len) {
|
||||||
|
const uint8_t* buf = static_cast<const uint8_t*>(data);
|
||||||
|
webrtc::ModuleRTPUtility::RTPHeaderParser parser(buf, len);
|
||||||
|
if (parser.RTCP()) {
|
||||||
|
Packet p;
|
||||||
|
p.channel = channel;
|
||||||
|
p.length = len;
|
||||||
|
if (parser.ParseRtcp(&p.header)) {
|
||||||
|
if (p.header.payloadType == 201) {
|
||||||
|
buf += 20;
|
||||||
|
len -= 20;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (TryParseREMB(buf, len, &p)) {
|
||||||
|
packets_.push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindREMBFor(uint32_t ssrc, double min_rate) const {
|
||||||
|
for (std::vector<Packet>::const_iterator it = packets_.begin();
|
||||||
|
it != packets_.end(); ++it) {
|
||||||
|
if (it->remb_bitrate >= min_rate && it->remb_ssrc.end() !=
|
||||||
|
std::find(it->remb_ssrc.begin(), it->remb_ssrc.end(), ssrc)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Packet {
|
||||||
|
Packet() : channel(-1), length(0), header(), remb_bitrate(0), remb_ssrc() {}
|
||||||
|
int channel;
|
||||||
|
int length;
|
||||||
|
webrtc::RTPHeader header;
|
||||||
|
double remb_bitrate;
|
||||||
|
std::vector<uint32_t> remb_ssrc;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool TryParseREMB(const uint8_t* buf, int length, Packet* p) {
|
||||||
|
if (length < 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (buf[0] != 'R' || buf[1] != 'E' || buf[2] != 'M' || buf[3] != 'B') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t ssrcs = buf[4];
|
||||||
|
uint8_t exp = buf[5] >> 2;
|
||||||
|
uint32_t mantissa = ((buf[5] & 0x03) << 16) + (buf[6] << 8) + buf[7];
|
||||||
|
double bitrate = mantissa * static_cast<double>(1 << exp);
|
||||||
|
p->remb_bitrate = bitrate;
|
||||||
|
|
||||||
|
if (length < (8 + 4 * ssrcs)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buf += 8;
|
||||||
|
for (uint8_t i = 0; i < ssrcs; ++i) {
|
||||||
|
uint32_t ssrc = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
|
||||||
|
p->remb_ssrc.push_back(ssrc);
|
||||||
|
buf += 4;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Packet> packets_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ViENetworkTest : public testing::Test {
|
||||||
|
protected:
|
||||||
|
ViENetworkTest() : vie_("ViENetworkTest"), channel_(-1), transport() {}
|
||||||
|
virtual ~ViENetworkTest() {}
|
||||||
|
|
||||||
|
virtual void SetUp() {
|
||||||
|
EXPECT_EQ(0, vie_.base->CreateChannel(channel_));
|
||||||
|
EXPECT_EQ(0, vie_.rtp_rtcp->SetRembStatus(channel_, false, true));
|
||||||
|
EXPECT_EQ(0, vie_.network->RegisterSendTransport(channel_, transport));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() {
|
||||||
|
unsigned int bandwidth = 0;
|
||||||
|
EXPECT_EQ(0, vie_.rtp_rtcp->GetEstimatedReceiveBandwidth(channel_,
|
||||||
|
&bandwidth));
|
||||||
|
EXPECT_EQ(bandwidth, 0u);
|
||||||
|
EXPECT_EQ(0, vie_.network->DeregisterSendTransport(channel_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReceiveASTPacketsForBWE() {
|
||||||
|
for (int i = 0; i < kPacketCount; ++i) {
|
||||||
|
int64_t time = webrtc::TickTime::MillisecondTimestamp();
|
||||||
|
webrtc::RTPHeader header;
|
||||||
|
header.ssrc = kSsrc1;
|
||||||
|
header.timestamp = i * 45000;
|
||||||
|
header.extension.hasAbsoluteSendTime = true;
|
||||||
|
header.extension.absoluteSendTime = i << (18 - 6);
|
||||||
|
EXPECT_EQ(0, vie_.network->ReceivedBWEPacket(channel_, time, kPacketSize,
|
||||||
|
header));
|
||||||
|
webrtc::SleepMs(kIntervalMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kSsrc1 = 667,
|
||||||
|
kSsrc2 = 668,
|
||||||
|
kPacketCount = 100,
|
||||||
|
kPacketSize = 1000,
|
||||||
|
kIntervalMs = 22
|
||||||
|
};
|
||||||
|
TbInterfaces vie_;
|
||||||
|
int channel_;
|
||||||
|
RtcpCollectorTransport transport;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ViENetworkTest, ReceiveBWEPacket_NoExtension) {
|
||||||
|
for (int i = 0; i < kPacketCount; ++i) {
|
||||||
|
int64_t time = webrtc::TickTime::MillisecondTimestamp();
|
||||||
|
webrtc::RTPHeader header;
|
||||||
|
header.ssrc = kSsrc1;
|
||||||
|
header.timestamp = i * 45000;
|
||||||
|
EXPECT_EQ(0, vie_.network->ReceivedBWEPacket(channel_, time, kPacketSize,
|
||||||
|
header));
|
||||||
|
webrtc::SleepMs(kIntervalMs);
|
||||||
|
}
|
||||||
|
EXPECT_FALSE(transport.FindREMBFor(kSsrc1, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ViENetworkTest, ReceiveBWEPacket_TOF) {
|
||||||
|
EXPECT_EQ(0, vie_.rtp_rtcp->SetReceiveTimestampOffsetStatus(channel_, true,
|
||||||
|
1));
|
||||||
|
for (int i = 0; i < kPacketCount; ++i) {
|
||||||
|
int64_t time = webrtc::TickTime::MillisecondTimestamp();
|
||||||
|
webrtc::RTPHeader header;
|
||||||
|
header.ssrc = kSsrc1;
|
||||||
|
header.timestamp = i * 45000;
|
||||||
|
header.extension.hasTransmissionTimeOffset = true;
|
||||||
|
header.extension.transmissionTimeOffset = 17;
|
||||||
|
EXPECT_EQ(0, vie_.network->ReceivedBWEPacket(channel_, time, kPacketSize,
|
||||||
|
header));
|
||||||
|
webrtc::SleepMs(kIntervalMs);
|
||||||
|
}
|
||||||
|
EXPECT_FALSE(transport.FindREMBFor(kSsrc1, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ViENetworkTest, ReceiveBWEPacket_AST) {
|
||||||
|
EXPECT_EQ(0, vie_.rtp_rtcp->SetReceiveAbsoluteSendTimeStatus(channel_, true,
|
||||||
|
1));
|
||||||
|
ReceiveASTPacketsForBWE();
|
||||||
|
EXPECT_TRUE(transport.FindREMBFor(kSsrc1, 100000.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ViENetworkTest, ReceiveBWEPacket_ASTx2) {
|
||||||
|
EXPECT_EQ(0, vie_.rtp_rtcp->SetReceiveAbsoluteSendTimeStatus(channel_, true,
|
||||||
|
1));
|
||||||
|
for (int i = 0; i < kPacketCount; ++i) {
|
||||||
|
int64_t time = webrtc::TickTime::MillisecondTimestamp();
|
||||||
|
webrtc::RTPHeader header;
|
||||||
|
header.ssrc = kSsrc1;
|
||||||
|
header.timestamp = i * 45000;
|
||||||
|
header.extension.hasAbsoluteSendTime = true;
|
||||||
|
header.extension.absoluteSendTime = i << (18 - 6);
|
||||||
|
EXPECT_EQ(0, vie_.network->ReceivedBWEPacket(channel_, time, kPacketSize,
|
||||||
|
header));
|
||||||
|
header.ssrc = kSsrc2;
|
||||||
|
header.timestamp += 171717;
|
||||||
|
EXPECT_EQ(0, vie_.network->ReceivedBWEPacket(channel_, time, kPacketSize,
|
||||||
|
header));
|
||||||
|
webrtc::SleepMs(kIntervalMs);
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(transport.FindREMBFor(kSsrc1, 200000.0));
|
||||||
|
EXPECT_TRUE(transport.FindREMBFor(kSsrc2, 200000.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ViENetworkTest, ReceiveBWEPacket_AST_DisabledReceive) {
|
||||||
|
EXPECT_EQ(0, vie_.rtp_rtcp->SetReceiveAbsoluteSendTimeStatus(channel_, false,
|
||||||
|
1));
|
||||||
|
ReceiveASTPacketsForBWE();
|
||||||
|
EXPECT_FALSE(transport.FindREMBFor(kSsrc1, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
@ -41,6 +41,7 @@
|
|||||||
'automated/two_windows_fixture.cc',
|
'automated/two_windows_fixture.cc',
|
||||||
'automated/vie_api_integration_test.cc',
|
'automated/vie_api_integration_test.cc',
|
||||||
'automated/vie_extended_integration_test.cc',
|
'automated/vie_extended_integration_test.cc',
|
||||||
|
'automated/vie_network_test.cc',
|
||||||
'automated/vie_standard_integration_test.cc',
|
'automated/vie_standard_integration_test.cc',
|
||||||
'automated/vie_video_verification_test.cc',
|
'automated/vie_video_verification_test.cc',
|
||||||
|
|
||||||
|
@ -2067,4 +2067,8 @@ void ViEChannel::RegisterSendFrameCountObserver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViEChannel::ReceivedBWEPacket(int64_t arrival_time_ms,
|
||||||
|
int payload_size, const RTPHeader& header) {
|
||||||
|
vie_receiver_.ReceivedBWEPacket(arrival_time_ms, payload_size, header);
|
||||||
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -351,6 +351,9 @@ class ViEChannel
|
|||||||
|
|
||||||
void RegisterSendFrameCountObserver(FrameCountObserver* observer);
|
void RegisterSendFrameCountObserver(FrameCountObserver* observer);
|
||||||
|
|
||||||
|
void ReceivedBWEPacket(int64_t arrival_time_ms, int payload_size,
|
||||||
|
const RTPHeader& header);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static bool ChannelDecodeThreadFunction(void* obj);
|
static bool ChannelDecodeThreadFunction(void* obj);
|
||||||
bool ChannelDecodeProcess();
|
bool ChannelDecodeProcess();
|
||||||
|
@ -214,8 +214,7 @@ int ViENetworkImpl::ReceivedBWEPacket(const int video_channel,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(solenberg): Implement!
|
vie_channel->ReceivedBWEPacket(arrival_time_ms, payload_size, header);
|
||||||
// vie_channel->OnReceivedAudioPacket(arrival_time_ms, payload_size, header);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -47,7 +47,8 @@ ViEReceiver::ViEReceiver(const int32_t channel_id,
|
|||||||
remote_bitrate_estimator_(remote_bitrate_estimator),
|
remote_bitrate_estimator_(remote_bitrate_estimator),
|
||||||
rtp_dump_(NULL),
|
rtp_dump_(NULL),
|
||||||
receiving_(false),
|
receiving_(false),
|
||||||
restored_packet_in_use_(false) {
|
restored_packet_in_use_(false),
|
||||||
|
receiving_ast_enabled_(false) {
|
||||||
assert(remote_bitrate_estimator);
|
assert(remote_bitrate_estimator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,9 +141,15 @@ bool ViEReceiver::SetReceiveTimestampOffsetStatus(bool enable, int id) {
|
|||||||
|
|
||||||
bool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
|
bool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
return rtp_header_parser_->RegisterRtpHeaderExtension(
|
if (rtp_header_parser_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionAbsoluteSendTime, id);
|
kRtpExtensionAbsoluteSendTime, id)) {
|
||||||
|
receiving_ast_enabled_ = true;
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
receiving_ast_enabled_ = false;
|
||||||
return rtp_header_parser_->DeregisterRtpHeaderExtension(
|
return rtp_header_parser_->DeregisterRtpHeaderExtension(
|
||||||
kRtpExtensionAbsoluteSendTime);
|
kRtpExtensionAbsoluteSendTime);
|
||||||
}
|
}
|
||||||
@ -183,6 +190,17 @@ bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
|
|||||||
return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
|
return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViEReceiver::ReceivedBWEPacket(
|
||||||
|
int64_t arrival_time_ms, int payload_size, const RTPHeader& header) {
|
||||||
|
// Only forward if the incoming packet *and* the channel are both configured
|
||||||
|
// to receive absolute sender time. RTP time stamps may have different rates
|
||||||
|
// for audio and video and shouldn't be mixed.
|
||||||
|
if (header.extension.hasAbsoluteSendTime && receiving_ast_enabled_) {
|
||||||
|
remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_size,
|
||||||
|
header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
|
int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet,
|
||||||
int rtp_packet_length,
|
int rtp_packet_length,
|
||||||
const PacketTime& packet_time) {
|
const PacketTime& packet_time) {
|
||||||
|
@ -87,6 +87,8 @@ class ViEReceiver : public RtpData {
|
|||||||
|
|
||||||
ReceiveStatistics* GetReceiveStatistics() const;
|
ReceiveStatistics* GetReceiveStatistics() const;
|
||||||
|
|
||||||
|
void ReceivedBWEPacket(int64_t arrival_time_ms, int payload_size,
|
||||||
|
const RTPHeader& header);
|
||||||
private:
|
private:
|
||||||
int InsertRTPPacket(const uint8_t* rtp_packet, int rtp_packet_length,
|
int InsertRTPPacket(const uint8_t* rtp_packet, int rtp_packet_length,
|
||||||
const PacketTime& packet_time);
|
const PacketTime& packet_time);
|
||||||
@ -119,6 +121,7 @@ class ViEReceiver : public RtpData {
|
|||||||
bool receiving_;
|
bool receiving_;
|
||||||
uint8_t restored_packet_[kViEMaxMtu];
|
uint8_t restored_packet_[kViEMaxMtu];
|
||||||
bool restored_packet_in_use_;
|
bool restored_packet_in_use_;
|
||||||
|
bool receiving_ast_enabled_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrt
|
} // namespace webrt
|
||||||
|
@ -1389,5 +1389,4 @@ int ViERTP_RTCPImpl::DeregisterSendFrameCountObserver(
|
|||||||
vie_channel->RegisterSendFrameCountObserver(NULL);
|
vie_channel->RegisterSendFrameCountObserver(NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
Loading…
Reference in New Issue
Block a user