Add DeliveryStatus enum to DeliverPacket().

Allows signalling why packet delivery failed. Especially enables
signaling that delivery fails because the incoming packet had an unknown
SSRC. This allows an application to react and create receivers for the
new streams.

R=mflodman@webrtc.org
BUG=3228

Review URL: https://webrtc-codereview.appspot.com/12289005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6150 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pbos@webrtc.org 2014-05-14 13:57:12 +00:00
parent 581e2172af
commit caba2d2a37
8 changed files with 55 additions and 33 deletions

View File

@ -25,7 +25,14 @@ const char* Version();
class PacketReceiver { class PacketReceiver {
public: public:
virtual bool DeliverPacket(const uint8_t* packet, size_t length) = 0; enum DeliveryStatus {
DELIVERY_OK,
DELIVERY_UNKNOWN_SSRC,
DELIVERY_PACKET_ERROR,
};
virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) = 0;
protected: protected:
virtual ~PacketReceiver() {} virtual ~PacketReceiver() {}

View File

@ -33,7 +33,7 @@ class MockReceiver : public PacketReceiver {
delete [] data; delete [] data;
} }
MOCK_METHOD2(DeliverPacket, bool(const uint8_t*, size_t)); MOCK_METHOD2(DeliverPacket, DeliveryStatus(const uint8_t*, size_t));
}; };
class FakeNetworkPipeTest : public ::testing::Test { class FakeNetworkPipeTest : public ::testing::Test {

View File

@ -86,11 +86,12 @@ class Call : public webrtc::Call, public PacketReceiver {
virtual uint32_t SendBitrateEstimate() OVERRIDE; virtual uint32_t SendBitrateEstimate() OVERRIDE;
virtual uint32_t ReceiveBitrateEstimate() OVERRIDE; virtual uint32_t ReceiveBitrateEstimate() OVERRIDE;
virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE; virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) OVERRIDE;
private: private:
bool DeliverRtcp(const uint8_t* packet, size_t length); DeliveryStatus DeliverRtcp(const uint8_t* packet, size_t length);
bool DeliverRtp(const RTPHeader& header, DeliveryStatus DeliverRtp(const RTPHeader& header,
const uint8_t* packet, const uint8_t* packet,
size_t length); size_t length);
@ -278,9 +279,12 @@ uint32_t Call::ReceiveBitrateEstimate() {
return 0; return 0;
} }
bool Call::DeliverRtcp(const uint8_t* packet, size_t length) { Call::PacketReceiver::DeliveryStatus Call::DeliverRtcp(const uint8_t* packet,
size_t length) {
// TODO(pbos): Figure out what channel needs it actually. // TODO(pbos): Figure out what channel needs it actually.
// Do NOT broadcast! Also make sure it's a valid packet. // Do NOT broadcast! Also make sure it's a valid packet.
// Return DELIVERY_UNKNOWN_SSRC if it can be determined that
// there's no receiver of the packet.
bool rtcp_delivered = false; bool rtcp_delivered = false;
{ {
ReadLockScoped read_lock(*receive_lock_); ReadLockScoped read_lock(*receive_lock_);
@ -303,30 +307,33 @@ bool Call::DeliverRtcp(const uint8_t* packet, size_t length) {
rtcp_delivered = true; rtcp_delivered = true;
} }
} }
return rtcp_delivered; return rtcp_delivered ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
} }
bool Call::DeliverRtp(const RTPHeader& header, Call::PacketReceiver::DeliveryStatus Call::DeliverRtp(const RTPHeader& header,
const uint8_t* packet, const uint8_t* packet,
size_t length) { size_t length) {
ReadLockScoped read_lock(*receive_lock_); ReadLockScoped read_lock(*receive_lock_);
std::map<uint32_t, VideoReceiveStream*>::iterator it = std::map<uint32_t, VideoReceiveStream*>::iterator it =
receive_ssrcs_.find(header.ssrc); receive_ssrcs_.find(header.ssrc);
if (it == receive_ssrcs_.end()) {
// TODO(pbos): Log some warning, SSRC without receiver. if (it == receive_ssrcs_.end())
return false; return DELIVERY_UNKNOWN_SSRC;
}
return it->second->DeliverRtp(static_cast<const uint8_t*>(packet), length); return it->second->DeliverRtp(static_cast<const uint8_t*>(packet), length)
? DELIVERY_OK
: DELIVERY_PACKET_ERROR;
} }
bool Call::DeliverPacket(const uint8_t* packet, size_t length) { Call::PacketReceiver::DeliveryStatus Call::DeliverPacket(const uint8_t* packet,
size_t length) {
// TODO(pbos): ExtensionMap if there are extensions. // TODO(pbos): ExtensionMap if there are extensions.
if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)))
return DeliverRtcp(packet, length); return DeliverRtcp(packet, length);
RTPHeader rtp_header; RTPHeader rtp_header;
if (!rtp_header_parser_->Parse(packet, static_cast<int>(length), &rtp_header)) if (!rtp_header_parser_->Parse(packet, static_cast<int>(length), &rtp_header))
return false; return DELIVERY_PACKET_ERROR;
return DeliverRtp(rtp_header, packet, length); return DeliverRtp(rtp_header, packet, length);
} }

View File

@ -258,7 +258,8 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
: channel_(channel), : channel_(channel),
voe_network_(voe_network), voe_network_(voe_network),
parser_(RtpHeaderParser::Create()) {} parser_(RtpHeaderParser::Create()) {}
virtual bool DeliverPacket(const uint8_t* packet, size_t length) { virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) OVERRIDE {
int ret; int ret;
if (parser_->IsRtcp(packet, static_cast<int>(length))) { if (parser_->IsRtcp(packet, static_cast<int>(length))) {
ret = voe_network_->ReceivedRTCPPacket( ret = voe_network_->ReceivedRTCPPacket(
@ -267,7 +268,7 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
ret = voe_network_->ReceivedRTPPacket( ret = voe_network_->ReceivedRTPPacket(
channel_, packet, static_cast<unsigned int>(length), PacketTime()); channel_, packet, static_cast<unsigned int>(length), PacketTime());
} }
return ret == 0; return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
} }
private: private:
@ -589,7 +590,8 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
} }
private: private:
virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE { virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) OVERRIDE {
VideoSendStream::Stats stats = send_stream_->GetStats(); VideoSendStream::Stats stats = send_stream_->GetStats();
if (stats.substreams.size() > 0) { if (stats.substreams.size() > 0) {
assert(stats.substreams.size() == 1); assert(stats.substreams.size() == 1);

View File

@ -840,7 +840,7 @@ TEST_F(CallTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
ReceivesPliAndRecovers(0); ReceivesPliAndRecovers(0);
} }
TEST_F(CallTest, SurvivesIncomingRtpPacketsToDestroyedReceiveStream) { TEST_F(CallTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
class PacketInputObserver : public PacketReceiver { class PacketInputObserver : public PacketReceiver {
public: public:
explicit PacketInputObserver(PacketReceiver* receiver) explicit PacketInputObserver(PacketReceiver* receiver)
@ -851,13 +851,16 @@ TEST_F(CallTest, SurvivesIncomingRtpPacketsToDestroyedReceiveStream) {
} }
private: private:
virtual bool DeliverPacket(const uint8_t* packet, size_t length) { virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) OVERRIDE {
if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) { if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
return receiver_->DeliverPacket(packet, length); return receiver_->DeliverPacket(packet, length);
} else { } else {
EXPECT_FALSE(receiver_->DeliverPacket(packet, length)); DeliveryStatus delivery_status =
receiver_->DeliverPacket(packet, length);
EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
delivered_packet_->Set(); delivered_packet_->Set();
return false; return delivery_status;
} }
} }

View File

@ -111,7 +111,8 @@ class VideoAnalyzer : public PacketReceiver,
virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; } virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; }
virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE { virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) OVERRIDE {
scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
RTPHeader header; RTPHeader header;
parser->Parse(packet, static_cast<int>(length), &header); parser->Parse(packet, static_cast<int>(length), &header);

View File

@ -268,7 +268,8 @@ class LowRateStreamObserver : public test::DirectTransport,
return test::DirectTransport::SendRtp(data, length); return test::DirectTransport::SendRtp(data, length);
} }
virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE { virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) OVERRIDE {
CriticalSectionScoped lock(crit_.get()); CriticalSectionScoped lock(crit_.get());
RTPHeader header; RTPHeader header;
EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header)); EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
@ -279,7 +280,7 @@ class LowRateStreamObserver : public test::DirectTransport,
remote_bitrate_estimator_->Process(); remote_bitrate_estimator_->Process();
} }
suspended_in_stats_ = send_stream_->GetStats().suspended; suspended_in_stats_ = send_stream_->GetStats().suspended;
return true; return DELIVERY_OK;
} }
virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE { virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE {

View File

@ -1160,13 +1160,14 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
} }
private: private:
virtual bool DeliverPacket(const uint8_t* packet, size_t length) { virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
size_t length) OVERRIDE {
if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)))
return true; return DELIVERY_OK;
RTPHeader header; RTPHeader header;
if (!parser_->Parse(packet, static_cast<int>(length), &header)) if (!parser_->Parse(packet, static_cast<int>(length), &header))
return true; return DELIVERY_PACKET_ERROR;
assert(send_stream_ != NULL); assert(send_stream_ != NULL);
VideoSendStream::Stats stats = send_stream_->GetStats(); VideoSendStream::Stats stats = send_stream_->GetStats();
if (!stats.substreams.empty()) { if (!stats.substreams.empty()) {
@ -1188,7 +1189,7 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
observation_complete_->Set(); observation_complete_->Set();
} }
} }
return true; return DELIVERY_OK;
} }
scoped_ptr<RtpRtcp> rtp_rtcp_; scoped_ptr<RtpRtcp> rtp_rtcp_;