(Auto)update libjingle 66388864-> 66406192

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6072 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
buildbot@webrtc.org 2014-05-07 14:50:35 +00:00
parent ed97bb0eb4
commit dd4742a9ef
4 changed files with 201 additions and 13 deletions

View File

@ -271,6 +271,7 @@ class FakeWebRtcVideoEngine
can_transmit_(true),
remote_rtx_ssrc_(-1),
rtx_send_payload_type(-1),
rtx_recv_payload_type(-1),
rtcp_status_(webrtc::kRtcpNone),
key_frame_request_method_(webrtc::kViEKeyFrameRequestNone),
tmmbr_(false),
@ -292,7 +293,8 @@ class FakeWebRtcVideoEngine
receive_bandwidth_(0),
reserved_transmit_bitrate_bps_(0),
suspend_below_min_bitrate_(false),
overuse_observer_(NULL) {
overuse_observer_(NULL),
last_recvd_payload_type_(-1) {
ssrcs_[0] = 0; // default ssrc.
memset(&send_codec, 0, sizeof(send_codec));
memset(&overuse_options_, 0, sizeof(overuse_options_));
@ -308,6 +310,7 @@ class FakeWebRtcVideoEngine
std::map<int, int> rtx_ssrcs_;
int remote_rtx_ssrc_;
int rtx_send_payload_type;
int rtx_recv_payload_type;
std::string cname_;
webrtc::ViERTCPMode rtcp_status_;
webrtc::ViEKeyFrameRequestMethod key_frame_request_method_;
@ -336,6 +339,7 @@ class FakeWebRtcVideoEngine
bool suspend_below_min_bitrate_;
webrtc::CpuOveruseObserver* overuse_observer_;
webrtc::CpuOveruseOptions overuse_options_;
int last_recvd_payload_type_;
};
class Capturer : public webrtc::ViEExternalCapture {
public:
@ -555,7 +559,9 @@ class FakeWebRtcVideoEngine
bool ReceiveCodecRegistered(int channel,
const webrtc::VideoCodec& codec) const {
WEBRTC_ASSERT_CHANNEL(channel);
return true;
const std::vector<webrtc::VideoCodec>& codecs =
channels_.find(channel)->second->recv_codecs;
return std::find(codecs.begin(), codecs.end(), codec) != codecs.end();
};
bool ExternalDecoderRegistered(int channel,
unsigned int pl_type) const {
@ -608,6 +614,10 @@ class FakeWebRtcVideoEngine
WEBRTC_CHECK_CHANNEL(channel);
return channels_[channel]->rtx_send_payload_type;
}
int GetRtxRecvPayloadType(int channel) {
WEBRTC_CHECK_CHANNEL(channel);
return channels_[channel]->rtx_recv_payload_type;
}
int GetRemoteRtxSsrc(int channel) {
WEBRTC_CHECK_CHANNEL(channel);
return channels_.find(channel)->second->remote_rtx_ssrc_;
@ -616,6 +626,10 @@ class FakeWebRtcVideoEngine
WEBRTC_ASSERT_CHANNEL(channel);
return channels_.find(channel)->second->suspend_below_min_bitrate_;
}
int GetLastRecvdPayloadType(int channel) const {
WEBRTC_CHECK_CHANNEL(channel);
return channels_.find(channel)->second->last_recvd_payload_type_;
}
unsigned int GetReservedTransmitBitrate(int channel) {
WEBRTC_ASSERT_CHANNEL(channel);
return channels_.find(channel)->second->reserved_transmit_bitrate_bps_;
@ -864,8 +878,18 @@ class FakeWebRtcVideoEngine
}
WEBRTC_STUB(RegisterSendTransport, (const int, webrtc::Transport&));
WEBRTC_STUB(DeregisterSendTransport, (const int));
WEBRTC_STUB(ReceivedRTPPacket, (const int, const void*, const int,
const webrtc::PacketTime&));
WEBRTC_FUNC(ReceivedRTPPacket, (const int channel,
const void* packet,
const int length,
const webrtc::PacketTime& packet_time)) {
WEBRTC_ASSERT_CHANNEL(channel);
ASSERT(length > 1);
uint8_t payload_type = static_cast<const uint8_t*>(packet)[1] & 0x7F;
channels_[channel]->last_recvd_payload_type_ = payload_type;
return 0;
}
WEBRTC_STUB(ReceivedRTCPPacket, (const int, const void*, const int));
// Not using WEBRTC_STUB due to bool return value
virtual bool IsIPv6Enabled(int channel) { return true; }
@ -975,7 +999,13 @@ class FakeWebRtcVideoEngine
channels_[channel]->rtx_send_payload_type = payload_type;
return 0;
}
WEBRTC_STUB(SetRtxReceivePayloadType, (const int, const uint8));
WEBRTC_FUNC(SetRtxReceivePayloadType, (const int channel,
const uint8 payload_type)) {
WEBRTC_CHECK_CHANNEL(channel);
channels_[channel]->rtx_recv_payload_type = payload_type;
return 0;
}
WEBRTC_STUB(SetStartSequenceNumber, (const int, unsigned short));
WEBRTC_FUNC(SetRTCPStatus,

View File

@ -1299,6 +1299,15 @@ bool WebRtcVideoEngine::ConvertFromCricketVideoCodec(
}
}
// Is this an RTX codec? Handled separately here since webrtc doesn't handle
// them as webrtc::VideoCodec internally.
if (!found && _stricmp(in_codec.name.c_str(), kRtxCodecName) == 0) {
talk_base::strcpyn(out_codec->plName, sizeof(out_codec->plName),
in_codec.name.c_str(), in_codec.name.length());
out_codec->plType = in_codec.id;
found = true;
}
if (!found) {
LOG(LS_ERROR) << "invalid codec type";
return false;
@ -1651,12 +1660,17 @@ WebRtcVideoMediaChannel::~WebRtcVideoMediaChannel() {
bool WebRtcVideoMediaChannel::SetRecvCodecs(
const std::vector<VideoCodec>& codecs) {
receive_codecs_.clear();
associated_payload_types_.clear();
for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
iter != codecs.end(); ++iter) {
if (engine()->FindCodec(*iter)) {
webrtc::VideoCodec wcodec;
if (engine()->ConvertFromCricketVideoCodec(*iter, &wcodec)) {
receive_codecs_.push_back(wcodec);
int apt;
if (iter->GetParam(cricket::kCodecParamAssociatedPayloadType, &apt)) {
associated_payload_types_[wcodec.plType] = apt;
}
}
} else {
LOG(LS_INFO) << "Unknown codec " << iter->name;
@ -2036,15 +2050,21 @@ bool WebRtcVideoMediaChannel::AddRecvStream(const StreamParams& sp) {
// Early receive added channel.
channel_id = (*channel_iterator).second->channel_id();
}
channel_iterator = recv_channels_.find(sp.first_ssrc());
// Set the corresponding RTX SSRC.
uint32 rtx_ssrc;
bool has_rtx = sp.GetFidSsrc(sp.first_ssrc(), &rtx_ssrc);
if (has_rtx && engine()->vie()->rtp()->SetRemoteSSRCType(
channel_id, webrtc::kViEStreamTypeRtx, rtx_ssrc) != 0) {
LOG_RTCERR3(SetRemoteSSRCType, channel_id, webrtc::kViEStreamTypeRtx,
rtx_ssrc);
return false;
if (has_rtx) {
LOG(LS_INFO) << "Setting rtx ssrc " << rtx_ssrc << " for stream "
<< sp.first_ssrc();
if (engine()->vie()->rtp()->SetRemoteSSRCType(
channel_id, webrtc::kViEStreamTypeRtx, rtx_ssrc) != 0) {
LOG_RTCERR3(SetRemoteSSRCType, channel_id, webrtc::kViEStreamTypeRtx,
rtx_ssrc);
return false;
}
rtx_to_primary_ssrc_[rtx_ssrc] = sp.first_ssrc();
}
// Get the default renderer.
@ -2102,6 +2122,17 @@ bool WebRtcVideoMediaChannel::RemoveRecvStreamInternal(uint32 ssrc) {
return false;
}
WebRtcVideoChannelRecvInfo* info = it->second;
// Remove any RTX SSRC mappings to this stream.
SsrcMap::iterator rtx_it = rtx_to_primary_ssrc_.begin();
while (rtx_it != rtx_to_primary_ssrc_.end()) {
if (rtx_it->second == ssrc) {
rtx_to_primary_ssrc_.erase(rtx_it++);
} else {
++rtx_it;
}
}
int channel_id = info->channel_id();
if (engine()->vie()->render()->RemoveRenderer(channel_id) != 0) {
LOG_RTCERR1(RemoveRenderer, channel_id);
@ -2695,10 +2726,10 @@ void WebRtcVideoMediaChannel::OnPacketReceived(
if (processing_channel == -1) {
// Allocate an unsignalled recv channel for processing in conference mode.
if (!InConferenceMode()) {
// If we cant find or allocate one, use the default.
// If we can't find or allocate one, use the default.
processing_channel = video_channel();
} else if (!CreateUnsignalledRecvChannel(ssrc, &processing_channel)) {
// If we cant create an unsignalled recv channel, drop the packet in
// If we can't create an unsignalled recv channel, drop the packet in
// conference mode.
return;
}
@ -3806,6 +3837,13 @@ bool WebRtcVideoMediaChannel::SetReceiveCodecs(
int red_type = -1;
int fec_type = -1;
int channel_id = info->channel_id();
// Build a map from payload types to video codecs so that we easily can find
// out if associated payload types are referring to valid codecs.
std::map<int, webrtc::VideoCodec*> pt_to_codec;
for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin();
it != receive_codecs_.end(); ++it) {
pt_to_codec[it->plType] = &(*it);
}
for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin();
it != receive_codecs_.end(); ++it) {
if (it->codecType == webrtc::kVideoCodecRED) {
@ -3813,6 +3851,32 @@ bool WebRtcVideoMediaChannel::SetReceiveCodecs(
} else if (it->codecType == webrtc::kVideoCodecULPFEC) {
fec_type = it->plType;
}
// If this is an RTX codec we have to verify that it is associated with
// a valid video codec which we have RTX support for.
if (_stricmp(it->plName, kRtxCodecName) == 0) {
std::map<int, int>::iterator apt_it = associated_payload_types_.find(
it->plType);
bool valid_apt = false;
if (apt_it != associated_payload_types_.end()) {
std::map<int, webrtc::VideoCodec*>::iterator codec_it =
pt_to_codec.find(apt_it->second);
// We currently only support RTX associated with VP8 due to limitations
// in webrtc where only one RTX payload type can be registered.
valid_apt = codec_it != pt_to_codec.end() &&
_stricmp(codec_it->second->plName, kVp8PayloadName) == 0;
}
if (!valid_apt) {
LOG(LS_ERROR) << "The RTX codec isn't associated with a known and "
"supported payload type";
return false;
}
if (engine()->vie()->rtp()->SetRtxReceivePayloadType(
channel_id, it->plType) != 0) {
LOG_RTCERR2(SetRtxReceivePayloadType, channel_id, it->plType);
return false;
}
continue;
}
if (engine()->vie()->codec()->SetReceiveCodec(channel_id, *it) != 0) {
LOG_RTCERR2(SetReceiveCodec, channel_id, it->plName);
return false;
@ -3840,8 +3904,20 @@ int WebRtcVideoMediaChannel::GetRecvChannelNum(uint32 ssrc) {
if (ssrc == first_receive_ssrc_) {
return vie_channel_;
}
int recv_channel = -1;
RecvChannelMap::iterator it = recv_channels_.find(ssrc);
return (it != recv_channels_.end()) ? it->second->channel_id() : -1;
if (it == recv_channels_.end()) {
// Check if we have an RTX stream registered on this SSRC.
SsrcMap::iterator rtx_it = rtx_to_primary_ssrc_.find(ssrc);
if (rtx_it != rtx_to_primary_ssrc_.end()) {
it = recv_channels_.find(rtx_it->second);
assert(it != recv_channels_.end());
recv_channel = it->second->channel_id();
}
} else {
recv_channel = it->second->channel_id();
}
return recv_channel;
}
// If the new frame size is different from the send codec size we set on vie,

View File

@ -201,6 +201,7 @@ class WebRtcVideoEngine : public sigslot::has_slots<>,
void SetTraceFilter(int filter);
void SetTraceOptions(const std::string& options);
bool InitVideoEngine();
bool VerifyApt(const VideoCodec& in, int expected_apt) const;
// webrtc::TraceCallback implementation.
virtual void Print(webrtc::TraceLevel level, const char* trace, int length);
@ -313,6 +314,7 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
private:
typedef std::map<uint32, WebRtcVideoChannelRecvInfo*> RecvChannelMap;
typedef std::map<uint32, WebRtcVideoChannelSendInfo*> SendChannelMap;
typedef std::map<uint32, uint32> SsrcMap;
typedef int (webrtc::ViERTP_RTCP::* ExtensionSetterFunction)(int, bool, int);
enum MediaDirection { MD_RECV, MD_SEND, MD_SENDRECV };
@ -433,7 +435,16 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
// work properly), resides in both recv_channels_ and send_channels_ with the
// ssrc key 0.
RecvChannelMap recv_channels_; // Contains all receive channels.
// A map from the SSRCs on which RTX packets are received to the media SSRCs
// the RTX packets are associated with. RTX packets will be delivered to the
// streams matching the primary SSRC.
SsrcMap rtx_to_primary_ssrc_;
std::vector<webrtc::VideoCodec> receive_codecs_;
// A map from codec payload types to their associated payload types, if any.
// TODO(holmer): This is a temporary solution until webrtc::VideoCodec has
// an associated payload type member, when it does we can rely on
// receive_codecs_.
std::map<int, int> associated_payload_types_;
bool render_started_;
uint32 first_receive_ssrc_;
std::vector<RtpHeaderExtension> receive_extensions_;

View File

@ -719,6 +719,76 @@ TEST_F(WebRtcVideoEngineTestFake, SetRecvCodecs) {
EXPECT_TRUE(vie_.ReceiveCodecRegistered(channel_num, wcodec));
}
// Test that we set our inbound RTX codecs properly.
TEST_F(WebRtcVideoEngineTestFake, SetRecvCodecsWithRtx) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
std::vector<cricket::VideoCodec> codecs;
cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0);
codecs.push_back(rtx_codec);
// Should fail since there's no associated payload type set.
EXPECT_FALSE(channel_->SetRecvCodecs(codecs));
codecs[0].SetParam("apt", 97);
// Should still fail since the we don't support RTX on this APT.
EXPECT_FALSE(channel_->SetRecvCodecs(codecs));
codecs[0].SetParam("apt", kVP8Codec.id);
// Should still fail since the associated payload type is unknown.
EXPECT_FALSE(channel_->SetRecvCodecs(codecs));
codecs.push_back(kVP8Codec);
EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
webrtc::VideoCodec wcodec;
// Should not have been registered as a WebRTC codec.
EXPECT_TRUE(engine_.ConvertFromCricketVideoCodec(rtx_codec, &wcodec));
EXPECT_STREQ("rtx", wcodec.plName);
EXPECT_FALSE(vie_.ReceiveCodecRegistered(channel_num, wcodec));
// The RTX payload type should have been set.
EXPECT_EQ(rtx_codec.id, vie_.GetRtxRecvPayloadType(channel_num));
}
// Test that RTX packets are routed to the correct video channel.
TEST_F(WebRtcVideoEngineTestFake, TestReceiveRtx) {
EXPECT_TRUE(SetupEngine());
// Setup three channels with associated RTX streams.
int channel_num[ARRAY_SIZE(kSsrcs3)];
for (size_t i = 0; i < ARRAY_SIZE(kSsrcs3); ++i) {
cricket::StreamParams params =
cricket::StreamParams::CreateLegacy(kSsrcs3[i]);
params.AddFidSsrc(kSsrcs3[i], kRtxSsrcs3[i]);
EXPECT_TRUE(channel_->AddRecvStream(params));
channel_num[i] = vie_.GetLastChannel();
}
// Register codecs.
std::vector<cricket::VideoCodec> codec_list;
codec_list.push_back(kVP8Codec720p);
cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0);
rtx_codec.SetParam("apt", kVP8Codec.id);
codec_list.push_back(rtx_codec);
EXPECT_TRUE(channel_->SetRecvCodecs(codec_list));
// Construct a fake RTX packet and verify that it is passed to the
// right WebRTC channel.
const size_t kDataLength = 12;
uint8_t data[kDataLength];
memset(data, 0, sizeof(data));
data[0] = 0x80;
data[1] = rtx_codec.id;
talk_base::SetBE32(&data[8], kRtxSsrcs3[1]);
talk_base::Buffer packet(data, kDataLength);
talk_base::PacketTime packet_time;
channel_->OnPacketReceived(&packet, packet_time);
EXPECT_NE(rtx_codec.id, vie_.GetLastRecvdPayloadType(channel_num[0]));
EXPECT_EQ(rtx_codec.id, vie_.GetLastRecvdPayloadType(channel_num[1]));
EXPECT_NE(rtx_codec.id, vie_.GetLastRecvdPayloadType(channel_num[2]));
}
// Test that channel connects and disconnects external capturer correctly.
TEST_F(WebRtcVideoEngineTestFake, HasExternalCapturer) {
EXPECT_TRUE(SetupEngine());
@ -2053,6 +2123,7 @@ TEST_F(WebRtcVideoEngineTest, FindCodec) {
EXPECT_TRUE(engine_.FindCodec(fec));
cricket::VideoCodec rtx(96, "rtx", 0, 0, 30, 0);
rtx.SetParam("apt", kVP8Codec.id);
EXPECT_TRUE(engine_.FindCodec(rtx));
}