Update libjingle to 59676287

R=wu@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5390 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
sergeyu@chromium.org 2014-01-15 23:15:54 +00:00
parent 7a2ca7c621
commit 4b26e2eee3
47 changed files with 1203 additions and 718 deletions

View File

@ -238,7 +238,7 @@ TEST_F(VideoSourceTest, MandatoryConstraintCif5Fps) {
ASSERT_TRUE(format != NULL);
EXPECT_EQ(352, format->width);
EXPECT_EQ(288, format->height);
EXPECT_EQ(5, format->framerate());
EXPECT_EQ(30, format->framerate());
}
// Test that the capture output is 720P if the camera support it and the
@ -491,7 +491,7 @@ TEST_F(VideoSourceTest, MixedOptionsAndConstraints) {
ASSERT_TRUE(format != NULL);
EXPECT_EQ(352, format->width);
EXPECT_EQ(288, format->height);
EXPECT_EQ(5, format->framerate());
EXPECT_EQ(30, format->framerate());
bool value = true;
EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
@ -554,6 +554,6 @@ TEST_F(VideoSourceTest, OptionalSubOneFpsConstraints) {
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
ASSERT_TRUE(format != NULL);
EXPECT_EQ(1, format->framerate());
EXPECT_EQ(30, format->framerate());
}

View File

@ -55,29 +55,22 @@ using cricket::TransportInfo;
namespace webrtc {
// Error messages
const char kSetLocalSdpFailed[] = "SetLocalDescription failed: ";
const char kSetRemoteSdpFailed[] = "SetRemoteDescription failed: ";
const char kCreateChannelFailed[] = "Failed to create channels.";
const char kBundleWithoutRtcpMux[] = "RTCP-MUX must be enabled when BUNDLE "
"is enabled.";
const char kCreateChannelFailed[] = "Failed to create channels.";
const char kInvalidCandidates[] = "Description contains invalid candidates.";
const char kInvalidSdp[] = "Invalid session description.";
const char kMlineMismatch[] =
"Offer and answer descriptions m-lines are not matching. "
"Rejecting answer.";
"Offer and answer descriptions m-lines are not matching. Rejecting answer.";
const char kPushDownTDFailed[] =
"Failed to push down transport description:";
const char kSdpWithoutCrypto[] = "Called with a SDP without crypto enabled.";
const char kSdpWithoutSdesAndDtlsDisabled[] =
"Called with an SDP without SDES crypto and DTLS disabled locally.";
const char kSdpWithoutIceUfragPwd[] =
"Called with an SDP without ice-ufrag and ice-pwd.";
"Called with a SDP without ice-ufrag and ice-pwd.";
const char kSdpWithoutSdesAndDtlsDisabled[] =
"Called with a SDP without SDES crypto and DTLS disabled locally.";
const char kSessionError[] = "Session error code: ";
const char kUpdateStateFailed[] = "Failed to update session state: ";
const char kPushDownOfferTDFailed[] =
"Failed to push down offer transport description.";
const char kPushDownPranswerTDFailed[] =
"Failed to push down pranswer transport description.";
const char kPushDownAnswerTDFailed[] =
"Failed to push down answer transport description.";
const char kSessionErrorDesc[] = "Session error description: ";
// Compares |answer| against |offer|. Comparision is done
// for number of m-lines in answer against offer. If matches true will be
@ -245,39 +238,60 @@ static bool GetTrackIdBySsrc(const SessionDescription* session_description,
return false;
}
static bool BadSdp(const std::string& desc, std::string* err_desc) {
static bool BadSdp(const std::string& source,
const std::string& type,
const std::string& reason,
std::string* err_desc) {
std::ostringstream desc;
desc << "Failed to set " << source << " " << type << " sdp: " << reason;
if (err_desc) {
*err_desc = desc;
*err_desc = desc.str();
}
LOG(LS_ERROR) << desc;
LOG(LS_ERROR) << desc.str();
return false;
}
static bool BadLocalSdp(const std::string& desc, std::string* err_desc) {
std::string set_local_sdp_failed = kSetLocalSdpFailed;
set_local_sdp_failed.append(desc);
return BadSdp(set_local_sdp_failed, err_desc);
}
static bool BadRemoteSdp(const std::string& desc, std::string* err_desc) {
std::string set_remote_sdp_failed = kSetRemoteSdpFailed;
set_remote_sdp_failed.append(desc);
return BadSdp(set_remote_sdp_failed, err_desc);
}
static bool BadSdp(cricket::ContentSource source,
const std::string& desc, std::string* err_desc) {
const std::string& type,
const std::string& reason,
std::string* err_desc) {
if (source == cricket::CS_LOCAL) {
return BadLocalSdp(desc, err_desc);
return BadSdp("local", type, reason, err_desc);
} else {
return BadRemoteSdp(desc, err_desc);
return BadSdp("remote", type, reason, err_desc);
}
}
static std::string SessionErrorMsg(cricket::BaseSession::Error error) {
std::ostringstream desc;
desc << kSessionError << error;
return desc.str();
static bool BadLocalSdp(const std::string& type,
const std::string& reason,
std::string* err_desc) {
return BadSdp(cricket::CS_LOCAL, type, reason, err_desc);
}
static bool BadRemoteSdp(const std::string& type,
const std::string& reason,
std::string* err_desc) {
return BadSdp(cricket::CS_REMOTE, type, reason, err_desc);
}
static bool BadOfferSdp(cricket::ContentSource source,
const std::string& reason,
std::string* err_desc) {
return BadSdp(source, SessionDescriptionInterface::kOffer, reason, err_desc);
}
static bool BadPranswerSdp(cricket::ContentSource source,
const std::string& reason,
std::string* err_desc) {
return BadSdp(source, SessionDescriptionInterface::kPrAnswer,
reason, err_desc);
}
static bool BadAnswerSdp(cricket::ContentSource source,
const std::string& reason,
std::string* err_desc) {
return BadSdp(source, SessionDescriptionInterface::kAnswer, reason, err_desc);
}
#define GET_STRING_OF_STATE(state) \
@ -311,20 +325,20 @@ static std::string GetStateString(cricket::BaseSession::State state) {
return result;
}
#define GET_STRING_OF_ERROR(err) \
#define GET_STRING_OF_ERROR_CODE(err) \
case cricket::BaseSession::err: \
result = #err; \
break;
static std::string GetErrorString(cricket::BaseSession::Error err) {
static std::string GetErrorCodeString(cricket::BaseSession::Error err) {
std::string result;
switch (err) {
GET_STRING_OF_ERROR(ERROR_NONE)
GET_STRING_OF_ERROR(ERROR_TIME)
GET_STRING_OF_ERROR(ERROR_RESPONSE)
GET_STRING_OF_ERROR(ERROR_NETWORK)
GET_STRING_OF_ERROR(ERROR_CONTENT)
GET_STRING_OF_ERROR(ERROR_TRANSPORT)
GET_STRING_OF_ERROR_CODE(ERROR_NONE)
GET_STRING_OF_ERROR_CODE(ERROR_TIME)
GET_STRING_OF_ERROR_CODE(ERROR_RESPONSE)
GET_STRING_OF_ERROR_CODE(ERROR_NETWORK)
GET_STRING_OF_ERROR_CODE(ERROR_CONTENT)
GET_STRING_OF_ERROR_CODE(ERROR_TRANSPORT)
default:
ASSERT(false);
break;
@ -332,12 +346,15 @@ static std::string GetErrorString(cricket::BaseSession::Error err) {
return result;
}
static bool SetSessionStateFailed(cricket::ContentSource source,
cricket::BaseSession::Error err,
std::string* err_desc) {
std::string set_state_err = kUpdateStateFailed;
set_state_err.append(GetErrorString(err));
return BadSdp(source, set_state_err, err_desc);
static std::string MakeErrorString(const std::string& error,
const std::string& desc) {
std::ostringstream ret;
ret << error << " " << desc;
return ret.str();
}
static std::string MakeTdErrorString(const std::string& desc) {
return MakeErrorString(kPushDownTDFailed, desc);
}
// Help class used to remember if a a remote peer has requested ice restart by
@ -604,15 +621,14 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
if (action == kOffer && !CreateChannels(local_desc_->description())) {
// TODO(mallinath) - Handle CreateChannel failure, as new local description
// is applied. Restore back to old description.
return BadLocalSdp(kCreateChannelFailed, err_desc);
return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc);
}
// Remove channel and transport proxies, if MediaContentDescription is
// rejected.
RemoveUnusedChannelsAndTransports(local_desc_->description());
if (!UpdateSessionState(action, cricket::CS_LOCAL,
local_desc_->description(), err_desc)) {
if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
return false;
}
// Kick starting the ice candidates allocation.
@ -627,7 +643,7 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
mediastream_signaling_->OnDtlsRoleReadyForSctp(role);
}
if (error() != cricket::BaseSession::ERROR_NONE) {
return BadLocalSdp(SessionErrorMsg(error()), err_desc);
return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
}
return true;
}
@ -647,7 +663,7 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
if (action == kOffer && !CreateChannels(desc->description())) {
// TODO(mallinath) - Handle CreateChannel failure, as new local description
// is applied. Restore back to old description.
return BadRemoteSdp(kCreateChannelFailed, err_desc);
return BadRemoteSdp(desc->type(), kCreateChannelFailed, err_desc);
}
// Remove channel and transport proxies, if MediaContentDescription is
@ -657,15 +673,14 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
// NOTE: Candidates allocation will be initiated only when SetLocalDescription
// is called.
set_remote_description(desc->description()->Copy());
if (!UpdateSessionState(action, cricket::CS_REMOTE,
desc->description(), err_desc)) {
if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) {
return false;
}
// Update remote MediaStreams.
mediastream_signaling_->OnRemoteDescriptionChanged(desc);
if (local_description() && !UseCandidatesInSessionDescription(desc)) {
return BadRemoteSdp(kInvalidCandidates, err_desc);
return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc);
}
// Copy all saved candidates.
@ -685,47 +700,47 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
}
if (error() != cricket::BaseSession::ERROR_NONE) {
return BadRemoteSdp(SessionErrorMsg(error()), err_desc);
return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc);
}
return true;
}
bool WebRtcSession::UpdateSessionState(
Action action, cricket::ContentSource source,
const cricket::SessionDescription* desc,
std::string* err_desc) {
// If there's already a pending error then no state transition should happen.
// But all call-sites should be verifying this before calling us!
ASSERT(error() == cricket::BaseSession::ERROR_NONE);
std::string td_err;
if (action == kOffer) {
if (!PushdownTransportDescription(source, cricket::CA_OFFER)) {
return BadSdp(source, kPushDownOfferTDFailed, err_desc);
if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) {
return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc);
}
SetState(source == cricket::CS_LOCAL ?
STATE_SENTINITIATE : STATE_RECEIVEDINITIATE);
if (error() != cricket::BaseSession::ERROR_NONE) {
return SetSessionStateFailed(source, error(), err_desc);
return BadOfferSdp(source, GetSessionErrorMsg(), err_desc);
}
} else if (action == kPrAnswer) {
if (!PushdownTransportDescription(source, cricket::CA_PRANSWER)) {
return BadSdp(source, kPushDownPranswerTDFailed, err_desc);
if (!PushdownTransportDescription(source, cricket::CA_PRANSWER, &td_err)) {
return BadPranswerSdp(source, MakeTdErrorString(td_err), err_desc);
}
EnableChannels();
SetState(source == cricket::CS_LOCAL ?
STATE_SENTPRACCEPT : STATE_RECEIVEDPRACCEPT);
if (error() != cricket::BaseSession::ERROR_NONE) {
return SetSessionStateFailed(source, error(), err_desc);
return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc);
}
} else if (action == kAnswer) {
if (!PushdownTransportDescription(source, cricket::CA_ANSWER)) {
return BadSdp(source, kPushDownAnswerTDFailed, err_desc);
if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) {
return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc);
}
MaybeEnableMuxingSupport();
EnableChannels();
SetState(source == cricket::CS_LOCAL ?
STATE_SENTACCEPT : STATE_RECEIVEDACCEPT);
if (error() != cricket::BaseSession::ERROR_NONE) {
return SetSessionStateFailed(source, error(), err_desc);
return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc);
}
}
return true;
@ -801,11 +816,9 @@ bool WebRtcSession::GetRemoteTrackId(uint32 ssrc, std::string* track_id) {
BaseSession::remote_description(), ssrc, track_id);
}
std::string WebRtcSession::BadStateErrMsg(
const std::string& type, State state) {
std::string WebRtcSession::BadStateErrMsg(State state) {
std::ostringstream desc;
desc << "Called with type in wrong state, "
<< "type: " << type << " state: " << GetStateString(state);
desc << "Called in wrong state: " << GetStateString(state);
return desc.str();
}
@ -1447,40 +1460,40 @@ bool WebRtcSession::HasRtcpMuxEnabled(
bool WebRtcSession::ValidateSessionDescription(
const SessionDescriptionInterface* sdesc,
cricket::ContentSource source, std::string* error_desc) {
cricket::ContentSource source, std::string* err_desc) {
std::string type;
if (error() != cricket::BaseSession::ERROR_NONE) {
return BadSdp(source, SessionErrorMsg(error()), error_desc);
return BadSdp(source, type, GetSessionErrorMsg(), err_desc);
}
if (!sdesc || !sdesc->description()) {
return BadSdp(source, kInvalidSdp, error_desc);
return BadSdp(source, type, kInvalidSdp, err_desc);
}
std::string type = sdesc->type();
type = sdesc->type();
Action action = GetAction(sdesc->type());
if (source == cricket::CS_LOCAL) {
if (!ExpectSetLocalDescription(action))
return BadSdp(source, BadStateErrMsg(type, state()), error_desc);
return BadLocalSdp(type, BadStateErrMsg(state()), err_desc);
} else {
if (!ExpectSetRemoteDescription(action))
return BadSdp(source, BadStateErrMsg(type, state()), error_desc);
return BadRemoteSdp(type, BadStateErrMsg(state()), err_desc);
}
// Verify crypto settings.
std::string crypto_error;
if (webrtc_session_desc_factory_->Secure() == cricket::SEC_REQUIRED &&
!VerifyCrypto(sdesc->description(), dtls_enabled_, &crypto_error)) {
return BadSdp(source, crypto_error, error_desc);
return BadSdp(source, type, crypto_error, err_desc);
}
// Verify ice-ufrag and ice-pwd.
if (!VerifyIceUfragPwdPresent(sdesc->description())) {
return BadSdp(source, kSdpWithoutIceUfragPwd, error_desc);
return BadSdp(source, type, kSdpWithoutIceUfragPwd, err_desc);
}
if (!ValidateBundleSettings(sdesc->description())) {
return BadSdp(source, kBundleWithoutRtcpMux, error_desc);
return BadSdp(source, type, kBundleWithoutRtcpMux, err_desc);
}
// Verify m-lines in Answer when compared against Offer.
@ -1489,7 +1502,7 @@ bool WebRtcSession::ValidateSessionDescription(
(source == cricket::CS_LOCAL) ? remote_description()->description() :
local_description()->description();
if (!VerifyMediaDescriptions(sdesc->description(), offer_desc)) {
return BadSdp(source, kMlineMismatch, error_desc);
return BadAnswerSdp(source, kMlineMismatch, err_desc);
}
}
@ -1526,4 +1539,11 @@ bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
(action == kPrAnswer && state() == STATE_RECEIVEDPRACCEPT));
}
std::string WebRtcSession::GetSessionErrorMsg() {
std::ostringstream desc;
desc << kSessionError << GetErrorCodeString(error()) << ". ";
desc << kSessionErrorDesc << error_desc() << ".";
return desc.str();
}
} // namespace webrtc

View File

@ -57,21 +57,17 @@ class IceRestartAnswerLatch;
class MediaStreamSignaling;
class WebRtcSessionDescriptionFactory;
extern const char kSetLocalSdpFailed[];
extern const char kSetRemoteSdpFailed[];
extern const char kCreateChannelFailed[];
extern const char kBundleWithoutRtcpMux[];
extern const char kCreateChannelFailed[];
extern const char kInvalidCandidates[];
extern const char kInvalidSdp[];
extern const char kMlineMismatch[];
extern const char kPushDownTDFailed[];
extern const char kSdpWithoutCrypto[];
extern const char kSdpWithoutSdesAndDtlsDisabled[];
extern const char kSdpWithoutIceUfragPwd[];
extern const char kSdpWithoutSdesAndDtlsDisabled[];
extern const char kSessionError[];
extern const char kUpdateStateFailed[];
extern const char kPushDownOfferTDFailed[];
extern const char kPushDownPranswerTDFailed[];
extern const char kPushDownAnswerTDFailed[];
extern const char kSessionErrorDesc[];
// ICE state callback interface.
class IceObserver {
@ -226,7 +222,6 @@ class WebRtcSession : public cricket::BaseSession,
// candidates allocation.
bool StartCandidatesAllocation();
bool UpdateSessionState(Action action, cricket::ContentSource source,
const cricket::SessionDescription* desc,
std::string* err_desc);
static Action GetAction(const std::string& type);
@ -285,7 +280,7 @@ class WebRtcSession : public cricket::BaseSession,
bool GetLocalTrackId(uint32 ssrc, std::string* track_id);
bool GetRemoteTrackId(uint32 ssrc, std::string* track_id);
std::string BadStateErrMsg(const std::string& type, State state);
std::string BadStateErrMsg(State state);
void SetIceConnectionState(PeerConnectionInterface::IceConnectionState state);
bool ValidateBundleSettings(const cricket::SessionDescription* desc);
@ -293,7 +288,7 @@ class WebRtcSession : public cricket::BaseSession,
// Below methods are helper methods which verifies SDP.
bool ValidateSessionDescription(const SessionDescriptionInterface* sdesc,
cricket::ContentSource source,
std::string* error_desc);
std::string* err_desc);
// Check if a call to SetLocalDescription is acceptable with |action|.
bool ExpectSetLocalDescription(Action action);
@ -303,6 +298,8 @@ class WebRtcSession : public cricket::BaseSession,
bool ValidateDtlsSetupAttribute(const cricket::SessionDescription* desc,
Action action);
std::string GetSessionErrorMsg();
talk_base::scoped_ptr<cricket::VoiceChannel> voice_channel_;
talk_base::scoped_ptr<cricket::VideoChannel> video_channel_;
talk_base::scoped_ptr<cricket::DataChannel> data_channel_;

View File

@ -87,15 +87,15 @@ using webrtc::SessionDescriptionInterface;
using webrtc::StreamCollection;
using webrtc::WebRtcSession;
using webrtc::kBundleWithoutRtcpMux;
using webrtc::kCreateChannelFailed;
using webrtc::kInvalidSdp;
using webrtc::kMlineMismatch;
using webrtc::kPushDownAnswerTDFailed;
using webrtc::kPushDownPranswerTDFailed;
using webrtc::kPushDownTDFailed;
using webrtc::kSdpWithoutCrypto;
using webrtc::kSdpWithoutIceUfragPwd;
using webrtc::kSdpWithoutSdesAndDtlsDisabled;
using webrtc::kSessionError;
using webrtc::kSetLocalSdpFailed;
using webrtc::kSetRemoteSdpFailed;
using webrtc::kSessionErrorDesc;
static const int kClientAddrPort = 0;
static const char kClientAddrHost1[] = "11.11.11.11";
@ -475,8 +475,8 @@ class WebRtcSessionTest : public testing::Test {
CreateRemoteOffer(options, cricket::SEC_DISABLED));
ASSERT_TRUE(offer != NULL);
VerifyNoCryptoParams(offer->description(), false);
SetRemoteDescriptionExpectError("Called with a SDP without crypto enabled",
offer);
SetRemoteDescriptionOfferExpectError(
"Called with a SDP without crypto enabled", offer);
const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
// Answer should be NULL as no crypto params in offer.
ASSERT_TRUE(answer == NULL);
@ -567,13 +567,26 @@ class WebRtcSessionTest : public testing::Test {
SetLocalDescriptionWithoutError(desc);
EXPECT_EQ(expected_state, session_->state());
}
void SetLocalDescriptionExpectError(const std::string& expected_error,
void SetLocalDescriptionExpectError(const std::string& action,
const std::string& expected_error,
SessionDescriptionInterface* desc) {
std::string error;
EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
EXPECT_NE(std::string::npos, error.find(kSetLocalSdpFailed));
std::string sdp_type = "local ";
sdp_type.append(action);
EXPECT_NE(std::string::npos, error.find(sdp_type));
EXPECT_NE(std::string::npos, error.find(expected_error));
}
void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
SessionDescriptionInterface* desc) {
SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
expected_error, desc);
}
void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
SessionDescriptionInterface* desc) {
SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
expected_error, desc);
}
void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
}
@ -582,13 +595,31 @@ class WebRtcSessionTest : public testing::Test {
SetRemoteDescriptionWithoutError(desc);
EXPECT_EQ(expected_state, session_->state());
}
void SetRemoteDescriptionExpectError(const std::string& expected_error,
void SetRemoteDescriptionExpectError(const std::string& action,
const std::string& expected_error,
SessionDescriptionInterface* desc) {
std::string error;
EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
EXPECT_NE(std::string::npos, error.find(kSetRemoteSdpFailed));
std::string sdp_type = "remote ";
sdp_type.append(action);
EXPECT_NE(std::string::npos, error.find(sdp_type));
EXPECT_NE(std::string::npos, error.find(expected_error));
}
void SetRemoteDescriptionOfferExpectError(
const std::string& expected_error, SessionDescriptionInterface* desc) {
SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
expected_error, desc);
}
void SetRemoteDescriptionPranswerExpectError(
const std::string& expected_error, SessionDescriptionInterface* desc) {
SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
expected_error, desc);
}
void SetRemoteDescriptionAnswerExpectError(
const std::string& expected_error, SessionDescriptionInterface* desc) {
SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
expected_error, desc);
}
void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
SessionDescriptionInterface** nocrypto_answer) {
@ -998,6 +1029,15 @@ TEST_F(WebRtcSessionTest, TestStunError) {
EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
}
TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
Init(NULL);
SessionDescriptionInterface* offer = NULL;
// Since |offer| is NULL, there's no way to tell if it's an offer or answer.
std::string unknown_action;
SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
}
// Test creating offers and receive answers and make sure the
// media engine creates the expected send and receive streams.
TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
@ -1109,6 +1149,20 @@ TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
EXPECT_EQ(0u, voice_channel_->send_streams().size());
}
TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
Init(NULL);
media_engine_->set_fail_create_channel(true);
SessionDescriptionInterface* offer = CreateOffer(NULL);
ASSERT_TRUE(offer != NULL);
// SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer.
SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
offer = CreateOffer(NULL);
ASSERT_TRUE(offer != NULL);
SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
}
// Test we will return fail when apply an offer that doesn't have
// crypto enabled.
TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
@ -1121,10 +1175,10 @@ TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
VerifyNoCryptoParams(offer->description(), false);
// SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer.
SetRemoteDescriptionExpectError(kSdpWithoutCrypto, offer);
SetRemoteDescriptionOfferExpectError(kSdpWithoutCrypto, offer);
offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
ASSERT_TRUE(offer != NULL);
SetLocalDescriptionExpectError(kSdpWithoutCrypto, offer);
SetLocalDescriptionOfferExpectError(kSdpWithoutCrypto, offer);
}
// Test we will return fail when apply an answer that doesn't have
@ -1137,7 +1191,7 @@ TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) {
// SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer.
SetRemoteDescriptionWithoutError(offer);
SetLocalDescriptionExpectError(kSdpWithoutCrypto, answer);
SetLocalDescriptionAnswerExpectError(kSdpWithoutCrypto, answer);
}
// Test we will return fail when apply an answer that doesn't have
@ -1150,7 +1204,7 @@ TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) {
// SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer.
SetLocalDescriptionWithoutError(offer);
SetRemoteDescriptionExpectError(kSdpWithoutCrypto, answer);
SetRemoteDescriptionAnswerExpectError(kSdpWithoutCrypto, answer);
}
// Test that we can create and set an offer with a DTLS fingerprint.
@ -1245,9 +1299,8 @@ TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
SessionDescriptionInterface* offer = CreateOffer(NULL);
SetLocalDescriptionWithoutError(offer);
offer = CreateOffer(NULL);
SetRemoteDescriptionExpectError(
"Called with type in wrong state, type: offer state: STATE_SENTINITIATE",
offer);
SetRemoteDescriptionOfferExpectError(
"Called in wrong state: STATE_SENTINITIATE", offer);
}
TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
@ -1256,10 +1309,8 @@ TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
SessionDescriptionInterface* offer = CreateOffer(NULL);
SetRemoteDescriptionWithoutError(offer);
offer = CreateOffer(NULL);
SetLocalDescriptionExpectError(
"Called with type in wrong state, type: "
"offer state: STATE_RECEIVEDINITIATE",
offer);
SetLocalDescriptionOfferExpectError(
"Called in wrong state: STATE_RECEIVEDINITIATE", offer);
}
TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
@ -1319,9 +1370,8 @@ TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
CreateOffer(NULL));
SessionDescriptionInterface* answer =
CreateRemoteAnswer(offer.get());
SetLocalDescriptionExpectError(
"Called with type in wrong state, type: answer state: STATE_INIT",
answer);
SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
answer);
}
TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
@ -1331,9 +1381,8 @@ TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
CreateOffer(NULL));
SessionDescriptionInterface* answer =
CreateRemoteAnswer(offer.get());
SetRemoteDescriptionExpectError(
"Called with type in wrong state, type: answer state: STATE_INIT",
answer);
SetRemoteDescriptionAnswerExpectError(
"Called in wrong state: STATE_INIT", answer);
}
TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
@ -1979,7 +2028,7 @@ TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
RemoveIceUfragPwdLines(offer.get(), &sdp);
SessionDescriptionInterface* modified_offer =
CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
SetLocalDescriptionExpectError(kSdpWithoutIceUfragPwd, modified_offer);
SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
}
// This test verifies that setRemoteDescription fails if
@ -1991,7 +2040,7 @@ TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
RemoveIceUfragPwdLines(offer.get(), &sdp);
SessionDescriptionInterface* modified_offer =
CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
SetRemoteDescriptionExpectError(kSdpWithoutIceUfragPwd, modified_offer);
SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
}
TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
@ -2071,11 +2120,11 @@ TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
JsepSessionDescription *local_offer =
new JsepSessionDescription(JsepSessionDescription::kOffer);
EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
SetLocalDescriptionExpectError(kBundleWithoutRtcpMux, local_offer);
SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
JsepSessionDescription *remote_offer =
new JsepSessionDescription(JsepSessionDescription::kOffer);
EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
SetRemoteDescriptionExpectError(kBundleWithoutRtcpMux, remote_offer);
SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
// Trying unmodified SDP.
SetLocalDescriptionWithoutError(offer);
}
@ -2319,13 +2368,13 @@ TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
SessionDescriptionInterface* pranswer_with_gice =
CreateSessionDescription(JsepSessionDescription::kPrAnswer,
original_offer_sdp, NULL);
SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed,
pranswer_with_gice);
SetRemoteDescriptionPranswerExpectError(kPushDownTDFailed,
pranswer_with_gice);
SessionDescriptionInterface* answer_with_gice =
CreateSessionDescription(JsepSessionDescription::kAnswer,
original_offer_sdp, NULL);
SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed,
answer_with_gice);
SetRemoteDescriptionAnswerExpectError(kPushDownTDFailed,
answer_with_gice);
}
// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
@ -2345,7 +2394,7 @@ TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
EXPECT_TRUE(modified_answer->Initialize(answer_copy,
answer->session_id(),
answer->session_version()));
SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer);
SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
// Modifying content names.
std::string sdp;
@ -2361,7 +2410,7 @@ TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
SessionDescriptionInterface* modified_answer1 =
CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1);
SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
SetRemoteDescriptionWithoutError(answer.release());
}
@ -2383,7 +2432,7 @@ TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
EXPECT_TRUE(modified_answer->Initialize(answer_copy,
answer->session_id(),
answer->session_version()));
SetLocalDescriptionExpectError(kMlineMismatch, modified_answer);
SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
SetLocalDescriptionWithoutError(answer);
}
@ -2537,7 +2586,7 @@ TEST_F(WebRtcSessionTest, TestSessionContentError) {
mediastream_signaling_.SendAudioVideoStream2();
SessionDescriptionInterface* answer =
CreateRemoteAnswer(session_->local_description());
SetRemoteDescriptionExpectError("ERROR_CONTENT", answer);
SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
}
// Runs the loopback call test with BUNDLE and STUN disabled.
@ -2550,20 +2599,27 @@ TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
TestLoopbackCall();
}
// Regression-test for a crash which should have been an error.
TEST_F(WebRtcSessionTest, TestNoStateTransitionPendingError) {
TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
Init(NULL);
cricket::MediaSessionOptions options;
options.has_audio = true;
options.has_video = true;
session_->SetError(cricket::BaseSession::ERROR_CONTENT);
cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT;
std::string error_code_str = "ERROR_CONTENT";
std::string error_desc = "Fake session error description.";
session_->SetError(error_code, error_desc);
SessionDescriptionInterface* offer = CreateRemoteOffer(options);
SessionDescriptionInterface* answer =
CreateRemoteAnswer(offer, options);
SetRemoteDescriptionExpectError(kSessionError, offer);
SetLocalDescriptionExpectError(kSessionError, answer);
// Not crashing is our success.
std::string action;
std::ostringstream session_error_msg;
session_error_msg << kSessionError << error_code_str << ". ";
session_error_msg << kSessionErrorDesc << error_desc << ".";
SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer);
SetLocalDescriptionExpectError(action, session_error_msg.str(), answer);
}
TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
@ -2803,8 +2859,8 @@ TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
audio->description.identity_fingerprint.reset(
talk_base::SSLFingerprint::CreateFromRfc4572(
talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint));
SetRemoteDescriptionExpectError(kSdpWithoutSdesAndDtlsDisabled,
offer);
SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesAndDtlsDisabled,
offer);
}
// This test verifies DSCP is properly applied on the media channels.

114
talk/base/sslfingerprint.cc Normal file
View File

@ -0,0 +1,114 @@
/*
* libjingle
* Copyright 2012, Google Inc.
* Copyright 2012, RTFM Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/base/sslfingerprint.h"
#include <ctype.h>
#include <string>
#include "talk/base/helpers.h"
#include "talk/base/messagedigest.h"
#include "talk/base/stringencode.h"
namespace talk_base {
SSLFingerprint* SSLFingerprint::Create(
const std::string& algorithm, const talk_base::SSLIdentity* identity) {
if (!identity) {
return NULL;
}
return Create(algorithm, &(identity->certificate()));
}
SSLFingerprint* SSLFingerprint::Create(
const std::string& algorithm, const talk_base::SSLCertificate* cert) {
uint8 digest_val[64];
size_t digest_len;
bool ret = cert->ComputeDigest(
algorithm, digest_val, sizeof(digest_val), &digest_len);
if (!ret) {
return NULL;
}
return new SSLFingerprint(algorithm, digest_val, digest_len);
}
SSLFingerprint* SSLFingerprint::CreateFromRfc4572(
const std::string& algorithm, const std::string& fingerprint) {
if (algorithm.empty() || !talk_base::IsFips180DigestAlgorithm(algorithm))
return NULL;
if (fingerprint.empty())
return NULL;
size_t value_len;
char value[talk_base::MessageDigest::kMaxSize];
value_len = talk_base::hex_decode_with_delimiter(value, sizeof(value),
fingerprint.c_str(),
fingerprint.length(),
':');
if (!value_len)
return NULL;
return new SSLFingerprint(algorithm,
reinterpret_cast<uint8*>(value),
value_len);
}
SSLFingerprint::SSLFingerprint(
const std::string& algorithm, const uint8* digest_in, size_t digest_len)
: algorithm(algorithm) {
digest.SetData(digest_in, digest_len);
}
SSLFingerprint::SSLFingerprint(const SSLFingerprint& from)
: algorithm(from.algorithm), digest(from.digest) {}
bool SSLFingerprint::operator==(const SSLFingerprint& other) const {
return algorithm == other.algorithm &&
digest == other.digest;
}
std::string SSLFingerprint::GetRfc4572Fingerprint() const {
std::string fingerprint =
talk_base::hex_encode_with_delimiter(
digest.data(), digest.length(), ':');
std::transform(fingerprint.begin(), fingerprint.end(),
fingerprint.begin(), ::toupper);
return fingerprint;
}
std::string SSLFingerprint::ToString() {
std::string fp_str = algorithm;
fp_str.append(" ");
fp_str.append(GetRfc4572Fingerprint());
return fp_str;
}
} // namespace talk_base

View File

@ -29,81 +29,35 @@
#ifndef TALK_BASE_SSLFINGERPRINT_H_
#define TALK_BASE_SSLFINGERPRINT_H_
#include <ctype.h>
#include <string>
#include "talk/base/buffer.h"
#include "talk/base/helpers.h"
#include "talk/base/messagedigest.h"
#include "talk/base/sslidentity.h"
#include "talk/base/stringencode.h"
namespace talk_base {
class SSLCertificate;
struct SSLFingerprint {
static SSLFingerprint* Create(const std::string& algorithm,
const talk_base::SSLIdentity* identity) {
if (!identity) {
return NULL;
}
return Create(algorithm, &(identity->certificate()));
}
const talk_base::SSLIdentity* identity);
static SSLFingerprint* Create(const std::string& algorithm,
const talk_base::SSLCertificate* cert) {
uint8 digest_val[64];
size_t digest_len;
bool ret = cert->ComputeDigest(
algorithm, digest_val, sizeof(digest_val), &digest_len);
if (!ret) {
return NULL;
}
return new SSLFingerprint(algorithm, digest_val, digest_len);
}
const talk_base::SSLCertificate* cert);
static SSLFingerprint* CreateFromRfc4572(const std::string& algorithm,
const std::string& fingerprint) {
if (algorithm.empty() || !talk_base::IsFips180DigestAlgorithm(algorithm))
return NULL;
if (fingerprint.empty())
return NULL;
size_t value_len;
char value[talk_base::MessageDigest::kMaxSize];
value_len = talk_base::hex_decode_with_delimiter(value, sizeof(value),
fingerprint.c_str(),
fingerprint.length(),
':');
if (!value_len)
return NULL;
return new SSLFingerprint(algorithm,
reinterpret_cast<uint8*>(value),
value_len);
}
const std::string& fingerprint);
SSLFingerprint(const std::string& algorithm, const uint8* digest_in,
size_t digest_len) : algorithm(algorithm) {
digest.SetData(digest_in, digest_len);
}
SSLFingerprint(const SSLFingerprint& from)
: algorithm(from.algorithm), digest(from.digest) {}
bool operator==(const SSLFingerprint& other) const {
return algorithm == other.algorithm &&
digest == other.digest;
}
size_t digest_len);
std::string GetRfc4572Fingerprint() const {
std::string fingerprint =
talk_base::hex_encode_with_delimiter(
digest.data(), digest.length(), ':');
std::transform(fingerprint.begin(), fingerprint.end(),
fingerprint.begin(), ::toupper);
return fingerprint;
}
SSLFingerprint(const SSLFingerprint& from);
bool operator==(const SSLFingerprint& other) const;
std::string GetRfc4572Fingerprint() const;
std::string ToString();
std::string algorithm;
talk_base::Buffer digest;

View File

@ -26,6 +26,7 @@
*/
#include "talk/examples/chat/chatapp.h"
#include "talk/base/stringencode.h"
#include "talk/examples/chat/consoletask.h"
#include "talk/examples/chat/textchatsendtask.h"
#include "talk/examples/chat/textchatreceivetask.h"

View File

@ -410,6 +410,7 @@
'base/ssladapter.cc',
'base/ssladapter.h',
'base/sslconfig.h',
'base/sslfingerprint.cc',
'base/sslfingerprint.h',
'base/sslidentity.cc',
'base/sslidentity.h',

View File

@ -281,7 +281,8 @@ class FakeVoiceMediaChannel : public RtpHelper<VoiceMediaChannel> {
}
return set_sending(flag != SEND_NOTHING);
}
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool AddRecvStream(const StreamParams& sp) {
if (!RtpHelper<VoiceMediaChannel>::AddRecvStream(sp))
return false;
@ -446,7 +447,9 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
explicit FakeVideoMediaChannel(FakeVideoEngine* engine)
: engine_(engine),
sent_intra_frame_(false),
requested_intra_frame_(false) {}
requested_intra_frame_(false),
start_bps_(-1),
max_bps_(-1) {}
~FakeVideoMediaChannel();
const std::vector<VideoCodec>& recv_codecs() const { return recv_codecs_; }
@ -457,6 +460,8 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
const std::map<uint32, VideoRenderer*>& renderers() const {
return renderers_;
}
int start_bps() const { return start_bps_; }
int max_bps() const { return max_bps_; }
bool GetSendStreamFormat(uint32 ssrc, VideoFormat* format) {
if (send_formats_.find(ssrc) == send_formats_.end()) {
return false;
@ -534,7 +539,14 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
bool HasCapturer(uint32 ssrc) const {
return capturers_.find(ssrc) != capturers_.end();
}
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
virtual bool SetStartSendBandwidth(int bps) {
start_bps_ = bps;
return true;
}
virtual bool SetMaxSendBandwidth(int bps) {
max_bps_ = bps;
return true;
}
virtual bool AddRecvStream(const StreamParams& sp) {
if (!RtpHelper<VideoMediaChannel>::AddRecvStream(sp))
return false;
@ -591,6 +603,8 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
bool sent_intra_frame_;
bool requested_intra_frame_;
VideoOptions options_;
int start_bps_;
int max_bps_;
};
class FakeSoundclipMedia : public SoundclipMedia {
@ -601,12 +615,11 @@ class FakeSoundclipMedia : public SoundclipMedia {
class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
public:
explicit FakeDataMediaChannel(void* unused)
: auto_bandwidth_(false), send_blocked_(false), max_bps_(-1) {}
: send_blocked_(false), max_bps_(-1) {}
~FakeDataMediaChannel() {}
const std::vector<DataCodec>& recv_codecs() const { return recv_codecs_; }
const std::vector<DataCodec>& send_codecs() const { return send_codecs_; }
const std::vector<DataCodec>& codecs() const { return send_codecs(); }
bool auto_bandwidth() const { return auto_bandwidth_; }
int max_bps() const { return max_bps_; }
virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs) {
@ -630,8 +643,8 @@ class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
set_playout(receive);
return true;
}
virtual bool SetSendBandwidth(bool autobw, int bps) {
auto_bandwidth_ = autobw;
virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) {
max_bps_ = bps;
return true;
}
@ -669,7 +682,6 @@ class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
std::vector<DataCodec> send_codecs_;
SendDataParams last_sent_data_params_;
std::string last_sent_data_;
bool auto_bandwidth_;
bool send_blocked_;
int max_bps_;
};

View File

@ -243,7 +243,8 @@ class FileVoiceChannel : public VoiceMediaChannel {
virtual bool AddRecvStream(const StreamParams& sp) { return true; }
virtual bool RemoveRecvStream(uint32 ssrc) { return true; }
virtual bool MuteStream(uint32 ssrc, bool on) { return false; }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool SetOptions(const AudioOptions& options) {
options_ = options;
return true;
@ -311,7 +312,8 @@ class FileVideoChannel : public VideoMediaChannel {
virtual bool AddRecvStream(const StreamParams& sp) { return true; }
virtual bool RemoveRecvStream(uint32 ssrc) { return true; }
virtual bool MuteStream(uint32 ssrc, bool on) { return false; }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool SetOptions(const VideoOptions& options) {
options_ = options;
return true;

View File

@ -183,9 +183,12 @@ bool HybridVideoMediaChannel::SetSendRtpHeaderExtensions(
active_channel_->SetSendRtpHeaderExtensions(extensions);
}
bool HybridVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) {
return active_channel_ &&
active_channel_->SetSendBandwidth(autobw, bps);
bool HybridVideoMediaChannel::SetStartSendBandwidth(int bps) {
return active_channel_ && active_channel_->SetStartSendBandwidth(bps);
}
bool HybridVideoMediaChannel::SetMaxSendBandwidth(int bps) {
return active_channel_ && active_channel_->SetMaxSendBandwidth(bps);
}
bool HybridVideoMediaChannel::SetSend(bool send) {

View File

@ -75,7 +75,8 @@ class HybridVideoMediaChannel : public VideoMediaChannel {
virtual bool SetSendStreamFormat(uint32 ssrc, const VideoFormat& format);
virtual bool SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions);
virtual bool SetSendBandwidth(bool autobw, int bps);
virtual bool SetStartSendBandwidth(int bps);
virtual bool SetMaxSendBandwidth(int bps);
virtual bool SetSend(bool send);
virtual bool AddRecvStream(const StreamParams& sp);

View File

@ -535,8 +535,10 @@ class MediaChannel : public sigslot::has_slots<> {
const std::vector<RtpHeaderExtension>& extensions) = 0;
virtual bool SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) = 0;
// Sets the rate control to use when sending data.
virtual bool SetSendBandwidth(bool autobw, int bps) = 0;
// Sets the initial bandwidth to use when sending starts.
virtual bool SetStartSendBandwidth(int bps) = 0;
// Sets the maximum allowed bandwidth to use when sending data.
virtual bool SetMaxSendBandwidth(int bps) = 0;
// Base method to send packet using NetworkInterface.
bool SendPacket(talk_base::Buffer* packet) {

View File

@ -290,8 +290,8 @@ void RtpDataMediaChannel::OnPacketReceived(
SignalDataReceived(params, data, data_len);
}
bool RtpDataMediaChannel::SetSendBandwidth(bool autobw, int bps) {
if (autobw || bps <= 0) {
bool RtpDataMediaChannel::SetMaxSendBandwidth(int bps) {
if (bps <= 0) {
bps = kDataMaxBandwidth;
}
send_limiter_.reset(new talk_base::RateLimiter(bps / 8, 1.0));

View File

@ -96,7 +96,8 @@ class RtpDataMediaChannel : public DataMediaChannel {
timing_ = timing;
}
virtual bool SetSendBandwidth(bool autobw, int bps);
virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps);
virtual bool SetRecvRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) { return true; }
virtual bool SetSendRtpHeaderExtensions(

View File

@ -387,7 +387,7 @@ TEST_F(RtpDataMediaChannelTest, SendDataRate) {
// With rtp overhead of 32 bytes, each one of our packets is 36
// bytes, or 288 bits. So, a limit of 872bps will allow 3 packets,
// but not four.
dmc->SetSendBandwidth(false, 872);
dmc->SetMaxSendBandwidth(872);
EXPECT_TRUE(dmc->SendData(params, payload, &result));
EXPECT_TRUE(dmc->SendData(params, payload, &result));

View File

@ -165,8 +165,8 @@ VideoAdapter::VideoAdapter()
frames_(0),
adapted_frames_(0),
adaption_changes_(0),
previous_width_(0),
previous_height_(0),
previous_width(0),
previous_height(0),
black_output_(false),
is_black_(false),
interval_next_frame_(0) {
@ -240,11 +240,11 @@ int VideoAdapter::GetOutputNumPixels() const {
// TODO(fbarchard): Add AdaptFrameRate function that only drops frames but
// not resolution.
bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
VideoFrame** out_frame) {
const VideoFrame** out_frame) {
talk_base::CritScope cs(&critical_section_);
if (!in_frame || !out_frame) {
return false;
}
talk_base::CritScope cs(&critical_section_);
++frames_;
// Update input to actual frame dimensions.
@ -306,8 +306,8 @@ bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
// resolution changes as well. Consider dropping the statistics into their
// own class which could be queried publically.
bool changed = false;
if (previous_width_ && (previous_width_ != (*out_frame)->GetWidth() ||
previous_height_ != (*out_frame)->GetHeight())) {
if (previous_width && (previous_width != (*out_frame)->GetWidth() ||
previous_height != (*out_frame)->GetHeight())) {
show = true;
++adaption_changes_;
changed = true;
@ -325,8 +325,8 @@ bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
<< "x" << (*out_frame)->GetHeight()
<< " Changed: " << (changed ? "true" : "false");
}
previous_width_ = (*out_frame)->GetWidth();
previous_height_ = (*out_frame)->GetHeight();
previous_width = (*out_frame)->GetWidth();
previous_height = (*out_frame)->GetHeight();
return true;
}

View File

@ -62,7 +62,7 @@ class VideoAdapter {
// successfully. Return false otherwise.
// output_frame_ is owned by the VideoAdapter that has the best knowledge on
// the output frame.
bool AdaptFrame(const VideoFrame* in_frame, VideoFrame** out_frame);
bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame);
void set_scale_third(bool enable) {
LOG(LS_INFO) << "Video Adapter third scaling is now "
@ -90,8 +90,8 @@ class VideoAdapter {
int frames_; // Number of input frames.
int adapted_frames_; // Number of frames scaled.
int adaption_changes_; // Number of changes in scale factor.
size_t previous_width_; // Previous adapter output width.
size_t previous_height_; // Previous adapter output height.
size_t previous_width; // Previous adapter output width.
size_t previous_height; // Previous adapter output height.
bool black_output_; // Flag to tell if we need to black output_frame_.
bool is_black_; // Flag to tell if output_frame_ is currently black.
int64 interval_next_frame_;

View File

@ -257,7 +257,7 @@ bool VideoCapturer::GetBestCaptureFormat(const VideoFormat& format,
best_format->width = best->width;
best_format->height = best->height;
best_format->fourcc = best->fourcc;
best_format->interval = talk_base::_max(format.interval, best->interval);
best_format->interval = best->interval;
LOG(LS_INFO) << " Best " << best_format->ToString() << " Interval "
<< best_format->interval << " distance " << best_distance;
}
@ -301,7 +301,7 @@ std::string VideoCapturer::ToString(const CapturedFrame* captured_frame) const {
std::ostringstream ss;
ss << fourcc_name << captured_frame->width << "x" << captured_frame->height
<< "x" << VideoFormat::IntervalToFps(captured_frame->elapsed_time);
<< "x" << VideoFormat::IntervalToFpsFloat(captured_frame->elapsed_time);
return ss.str();
}
@ -475,25 +475,14 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
<< desired_width << " x " << desired_height;
return;
}
VideoFrame* adapted_frame = &i420_frame;
if (!SignalAdaptFrame.is_empty() && !IsScreencast()) {
VideoFrame* out_frame = NULL;
SignalAdaptFrame(this, adapted_frame, &out_frame);
if (!out_frame) {
return; // VideoAdapter dropped the frame.
}
adapted_frame = out_frame;
}
if (!muted_ && !ApplyProcessors(adapted_frame)) {
if (!muted_ && !ApplyProcessors(&i420_frame)) {
// Processor dropped the frame.
return;
}
if (muted_) {
adapted_frame->SetToBlack();
i420_frame.SetToBlack();
}
SignalVideoFrame(this, adapted_frame);
SignalVideoFrame(this, &i420_frame);
#endif // VIDEO_FRAME_NAME
}
@ -577,9 +566,9 @@ int64 VideoCapturer::GetFormatDistance(const VideoFormat& desired,
int desired_width = desired.width;
int desired_height = desired.height;
int64 delta_w = supported.width - desired_width;
int64 supported_fps = VideoFormat::IntervalToFps(supported.interval);
int64 delta_fps =
supported_fps - VideoFormat::IntervalToFps(desired.interval);
float supported_fps = VideoFormat::IntervalToFpsFloat(supported.interval);
float delta_fps =
supported_fps - VideoFormat::IntervalToFpsFloat(desired.interval);
// Check height of supported height compared to height we would like it to be.
int64 aspect_h =
desired_width ? supported.width * desired_height / desired_width
@ -606,9 +595,9 @@ int64 VideoCapturer::GetFormatDistance(const VideoFormat& desired,
// Require camera fps to be at least 96% of what is requested, or higher,
// if resolution differs. 96% allows for slight variations in fps. e.g. 29.97
if (delta_fps < 0) {
int64 min_desirable_fps = delta_w ?
VideoFormat::IntervalToFps(desired.interval) * 29 / 30 :
VideoFormat::IntervalToFps(desired.interval) * 24 / 30;
float min_desirable_fps = delta_w ?
VideoFormat::IntervalToFpsFloat(desired.interval) * 28.f / 30.f :
VideoFormat::IntervalToFpsFloat(desired.interval) * 23.f / 30.f;
delta_fps = -delta_fps;
if (supported_fps < min_desirable_fps) {
distance |= static_cast<int64>(1) << 62;
@ -616,10 +605,11 @@ int64 VideoCapturer::GetFormatDistance(const VideoFormat& desired,
distance |= static_cast<int64>(1) << 15;
}
}
int64 idelta_fps = static_cast<int>(delta_fps);
// 12 bits for width and height and 8 bits for fps and fourcc.
distance |=
(delta_w << 28) | (delta_h << 16) | (delta_fps << 8) | delta_fourcc;
(delta_w << 28) | (delta_h << 16) | (idelta_fps << 8) | delta_fourcc;
return distance;
}

View File

@ -255,11 +255,6 @@ class VideoCapturer
// Signal the captured frame to downstream.
sigslot::signal2<VideoCapturer*, const CapturedFrame*,
sigslot::multi_threaded_local> SignalFrameCaptured;
// If slots are connected to SignalAdaptFrame, this signals with parameters
// of this capturer instance, the input video frame and output frame
// pointer, respectively.
sigslot::signal3<VideoCapturer*, const VideoFrame*, VideoFrame**,
sigslot::multi_threaded_local> SignalAdaptFrame;
// Signal the captured frame converted to I420 to downstream.
sigslot::signal2<VideoCapturer*, const VideoFrame*,
sigslot::multi_threaded_local> SignalVideoFrame;

View File

@ -507,23 +507,23 @@ TEST_F(VideoCapturerTest, TestFpsFormats) {
cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
cricket::VideoFormat best;
// expect 30 fps to choose 30 fps format
// Expect 30 fps to choose 30 fps format.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
EXPECT_EQ(640, best.width);
EXPECT_EQ(400, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
// expect 20 fps to choose 20 fps format
// Expect 20 fps to choose 30 fps format.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
EXPECT_EQ(640, best.width);
EXPECT_EQ(400, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
// expect 10 fps to choose 15 fps format but set fps to 10
// Expect 10 fps to choose 15 fps format and set fps to 15.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
EXPECT_EQ(640, best.width);
EXPECT_EQ(480, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
// We have VGA 60 fps and 15 fps. Choose best fps.
supported_formats.clear();
@ -539,23 +539,23 @@ TEST_F(VideoCapturerTest, TestFpsFormats) {
cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
capturer_.ResetSupportedFormats(supported_formats);
// expect 30 fps to choose 60 fps format, but will set best fps to 30
// Expect 30 fps to choose 60 fps format and will set best fps to 60.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
EXPECT_EQ(640, best.width);
EXPECT_EQ(480, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
// expect 20 fps to choose 60 fps format, but will set best fps to 20
// Expect 20 fps to choose 60 fps format, and will set best fps to 60.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
EXPECT_EQ(640, best.width);
EXPECT_EQ(480, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
// expect 10 fps to choose 10 fps
// Expect 10 fps to choose 15 fps.
EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
EXPECT_EQ(640, best.width);
EXPECT_EQ(480, best.height);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval);
EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
}
TEST_F(VideoCapturerTest, TestRequest16x10_9) {

View File

@ -236,7 +236,8 @@ std::string VideoFormat::ToString() const {
}
std::ostringstream ss;
ss << fourcc_name << width << "x" << height << "x" << IntervalToFps(interval);
ss << fourcc_name << width << "x" << height << "x"
<< IntervalToFpsFloat(interval);
return ss.str();
}

View File

@ -212,11 +212,17 @@ struct VideoFormat : VideoFormatPod {
}
static int IntervalToFps(int64 interval) {
// Normalize the interval first.
interval = talk_base::_max(interval, kMinimumInterval);
return static_cast<int>(talk_base::kNumNanosecsPerSec / interval);
}
static float IntervalToFpsFloat(int64 interval) {
if (!interval) {
return 0.f;
}
return static_cast<float>(talk_base::kNumNanosecsPerSec) /
static_cast<float>(interval);
}
bool operator==(const VideoFormat& format) const {
return width == format.width && height == format.height &&
interval == format.interval && fourcc == format.fourcc;

View File

@ -70,7 +70,7 @@ TEST(VideoCommonTest, TestVideoFormatIsSize0x0) {
// Test ToString: print fourcc when it is printable.
TEST(VideoCommonTest, TestVideoFormatToString) {
VideoFormat format;
EXPECT_EQ("0x0x10000", format.ToString());
EXPECT_EQ("0x0x0", format.ToString());
format.fourcc = FOURCC_I420;
format.width = 640;

View File

@ -928,12 +928,11 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_TRUE(channel_->SetCapturer(5678, NULL));
}
// Test that we can set the bandwidth to auto or a specific value.
// Test that we can set the bandwidth.
void SetSendBandwidth() {
EXPECT_TRUE(channel_->SetSendBandwidth(true, -1));
EXPECT_TRUE(channel_->SetSendBandwidth(true, 128 * 1024));
EXPECT_TRUE(channel_->SetSendBandwidth(false, -1));
EXPECT_TRUE(channel_->SetSendBandwidth(false, 128 * 1024));
EXPECT_TRUE(channel_->SetStartSendBandwidth(64 * 1024));
EXPECT_TRUE(channel_->SetMaxSendBandwidth(-1)); // <= 0 means unlimited.
EXPECT_TRUE(channel_->SetMaxSendBandwidth(128 * 1024));
}
// Test that we can set the SSRC for the default send source.
void SetSendSsrc() {

View File

@ -145,7 +145,8 @@ class LinphoneVoiceChannel : public VoiceMediaChannel {
virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet?
virtual bool SetRtcpCName(const std::string& cname) { return true; }
virtual bool Mute(bool on) { return mute_; }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool SetOptions(int options) { return true; }
virtual bool SetRecvRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) { return true; }

View File

@ -30,7 +30,7 @@
#include <errno.h>
#include <string>
#include <set>
#include <vector>
namespace cricket {
// Some ERRNO values get re-#defined to WSA* equivalents in some talk/
@ -166,7 +166,8 @@ class SctpDataMediaChannel : public DataMediaChannel,
// TODO(pthatcher): Cleanup MediaChannel interface, or at least
// don't try calling these and return false. Right now, things
// don't work if we return false.
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
virtual bool SetStartSendBandwidth(int bps) { return true; }
virtual bool SetMaxSendBandwidth(int bps) { return true; }
virtual bool SetRecvRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) { return true; }
virtual bool SetSendRtpHeaderExtensions(
@ -216,6 +217,7 @@ class SctpDataMediaChannel : public DataMediaChannel,
talk_base::Buffer* buffer);
void OnNotificationFromSctp(talk_base::Buffer* buffer);
void OnNotificationAssocChange(const sctp_assoc_change& change);
void OnStreamResetEvent(const struct sctp_stream_reset_event* evt);
// Responsible for marshalling incoming data to the channels listeners, and

View File

@ -632,6 +632,10 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
}
}
bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame) {
*out_frame = NULL;
return video_adapter_->AdaptFrame(in_frame, out_frame);
}
int CurrentAdaptReason() const {
return video_adapter_->adapt_reason();
}
@ -672,18 +676,9 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
// video capturer.
video_adapter_->SetInputFormat(*capture_format);
}
// TODO(thorcarpenter): When the adapter supports "only frame dropping"
// mode, also hook it up to screencast capturers.
video_capturer->SignalAdaptFrame.connect(
this, &WebRtcVideoChannelSendInfo::AdaptFrame);
}
}
void AdaptFrame(VideoCapturer* capturer, const VideoFrame* input,
VideoFrame** adapted) {
video_adapter_->AdaptFrame(input, adapted);
}
void ApplyCpuOptions(const VideoOptions& options) {
bool cpu_adapt, cpu_smoothing, adapt_third;
float low, med, high;
@ -2470,7 +2465,9 @@ bool WebRtcVideoMediaChannel::SetCapturer(uint32 ssrc,
MaybeDisconnectCapturer(old_capturer);
send_channel->set_video_capturer(capturer);
MaybeConnectCapturer(capturer);
capturer->SignalVideoFrame.connect(
this,
&WebRtcVideoMediaChannel::SendFrame);
if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) {
capturer->UpdateAspectRatio(ratio_w_, ratio_h_);
}
@ -2624,11 +2621,27 @@ bool WebRtcVideoMediaChannel::SetSendRtpHeaderExtensions(
return true;
}
bool WebRtcVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) {
LOG(LS_INFO) << "WebRtcVideoMediaChanne::SetSendBandwidth";
bool WebRtcVideoMediaChannel::SetStartSendBandwidth(int bps) {
LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetStartSendBandwidth";
if (!send_codec_) {
LOG(LS_INFO) << "The send codec has not been set up yet";
return true;
}
// On success, SetSendCodec() will reset |send_start_bitrate_| to |bps/1000|,
// by calling MaybeChangeStartBitrate. That method will also clamp the
// start bitrate between min and max, consistent with the override behavior
// in SetMaxSendBandwidth.
return SetSendCodec(*send_codec_,
send_min_bitrate_, bps / 1000, send_max_bitrate_);
}
bool WebRtcVideoMediaChannel::SetMaxSendBandwidth(int bps) {
LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetMaxSendBandwidth";
if (InConferenceMode()) {
LOG(LS_INFO) << "Conference mode ignores SetSendBandWidth";
LOG(LS_INFO) << "Conference mode ignores SetMaxSendBandwidth";
return true;
}
@ -2637,28 +2650,17 @@ bool WebRtcVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) {
return true;
}
int min_bitrate;
int start_bitrate;
int max_bitrate;
if (autobw) {
// Use the default values for min bitrate.
min_bitrate = send_min_bitrate_;
// Use the default value or the bps for the max
max_bitrate = (bps <= 0) ? send_max_bitrate_ : (bps / 1000);
// Maximum start bitrate can be kStartVideoBitrate.
start_bitrate = talk_base::_min(kStartVideoBitrate, max_bitrate);
} else {
// Use the default start or the bps as the target bitrate.
int target_bitrate = (bps <= 0) ? kStartVideoBitrate : (bps / 1000);
min_bitrate = target_bitrate;
start_bitrate = target_bitrate;
max_bitrate = target_bitrate;
}
// Use the default value or the bps for the max
int max_bitrate = (bps <= 0) ? send_max_bitrate_ : (bps / 1000);
// Reduce the current minimum and start bitrates if necessary.
int min_bitrate = talk_base::_min(send_min_bitrate_, max_bitrate);
int start_bitrate = talk_base::_min(send_start_bitrate_, max_bitrate);
if (!SetSendCodec(*send_codec_, min_bitrate, start_bitrate, max_bitrate)) {
return false;
}
LogSendCodecChange("SetSendBandwidth()");
LogSendCodecChange("SetMaxSendBandwidth()");
return true;
}
@ -2860,6 +2862,7 @@ bool WebRtcVideoMediaChannel::GetRenderer(uint32 ssrc,
return true;
}
// TODO(zhurunz): Add unittests to test this function.
void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer,
const VideoFrame* frame) {
// If the |capturer| is registered to any send channel, then send the frame

View File

@ -276,7 +276,8 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
const std::vector<RtpHeaderExtension>& extensions);
virtual bool SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions);
virtual bool SetSendBandwidth(bool autobw, int bps);
virtual bool SetStartSendBandwidth(int bps);
virtual bool SetMaxSendBandwidth(int bps);
virtual bool SetOptions(const VideoOptions &options);
virtual bool GetOptions(VideoOptions *options) const {
*options = options_;
@ -292,6 +293,8 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
bool SendFrame(WebRtcVideoChannelSendInfo* channel_info,
const VideoFrame* frame, bool is_screencast);
void AdaptAndSendFrame(VideoCapturer* capturer, const VideoFrame* frame);
// Thunk functions for use with HybridVideoEngine
void OnLocalFrame(VideoCapturer* capturer, const VideoFrame* frame) {
SendFrame(0u, frame, capturer->IsScreencast());

View File

@ -1100,30 +1100,62 @@ TEST_F(WebRtcVideoEngineTestFake, SetBandwidthAuto) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
EXPECT_TRUE(channel_->SetSendBandwidth(true, cricket::kAutoBandwidth));
EXPECT_TRUE(channel_->SetMaxSendBandwidth(cricket::kAutoBandwidth));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height);
}
// Test that we set bandwidth properly when using auto with upper bound.
TEST_F(WebRtcVideoEngineTestFake, SetBandwidthAutoCapped) {
TEST_F(WebRtcVideoEngineTestFake, SetBandwidthCapped) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
EXPECT_TRUE(channel_->SetSendBandwidth(true, 768000));
EXPECT_TRUE(channel_->SetMaxSendBandwidth(768000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, 768U);
}
// Test that we set bandwidth properly when using a fixed bandwidth.
TEST_F(WebRtcVideoEngineTestFake, SetBandwidthFixed) {
// Test that we reduce the start bandwidth when the requested max is less than
// the default start bandwidth.
TEST_F(WebRtcVideoEngineTestFake, SetMaxBandwidthBelowDefaultStart) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
EXPECT_TRUE(channel_->SetSendBandwidth(false, 768000));
int max_bandwidth_kbps = (kMinBandwidthKbps + kStartBandwidthKbps) / 2;
EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth_kbps * 1000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
768U, 768U, 768U);
max_bandwidth_kbps, kMinBandwidthKbps, max_bandwidth_kbps);
}
// Test that SetSendBandwidth is ignored in conference mode.
// Test that we reduce the min bandwidth when the requested max is less than
// the min bandwidth.
TEST_F(WebRtcVideoEngineTestFake, SetMaxBandwidthBelowMin) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
int max_bandwidth_kbps = kMinBandwidthKbps / 2;
EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth_kbps * 1000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
max_bandwidth_kbps, max_bandwidth_kbps, max_bandwidth_kbps);
}
// Test that the start bandwidth can be controlled separately from the max
// bandwidth.
TEST_F(WebRtcVideoEngineTestFake, SetStartBandwidth) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
int start_bandwidth_kbps = kStartBandwidthKbps + 1;
EXPECT_TRUE(channel_->SetStartSendBandwidth(start_bandwidth_kbps * 1000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
kMaxBandwidthKbps, kMinBandwidthKbps, start_bandwidth_kbps);
// Check that SetMaxSendBandwidth doesn't overwrite the start bandwidth.
int max_bandwidth_kbps = kMaxBandwidthKbps + 1;
EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bandwidth_kbps * 1000));
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
max_bandwidth_kbps, kMinBandwidthKbps, start_bandwidth_kbps);
}
// Test that SetMaxSendBandwidth is ignored in conference mode.
TEST_F(WebRtcVideoEngineTestFake, SetBandwidthInConference) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
@ -1134,7 +1166,7 @@ TEST_F(WebRtcVideoEngineTestFake, SetBandwidthInConference) {
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height);
// Set send bandwidth.
EXPECT_TRUE(channel_->SetSendBandwidth(false, 768000));
EXPECT_TRUE(channel_->SetMaxSendBandwidth(768000));
// Verify bitrate not changed.
webrtc::VideoCodec gcodec;
@ -1159,12 +1191,11 @@ TEST_F(WebRtcVideoEngineTestFake, SetBandwidthScreencast) {
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(123)));
EXPECT_TRUE(channel_->SetSendCodecs(codec_list));
EXPECT_TRUE(channel_->SetSendBandwidth(false, 111000));
EXPECT_TRUE(channel_->SetMaxSendBandwidth(111000));
EXPECT_TRUE(channel_->SetSend(true));
SendI420ScreencastFrame(kVP8Codec.width, kVP8Codec.height);
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0,
111, 111, 111);
VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height, 0, 111);
}
@ -1243,7 +1274,11 @@ TEST_F(WebRtcVideoEngineTestFake, SetOptionsWithDenoising) {
EXPECT_FALSE(vie_.GetCaptureDenoising(capture_id));
}
TEST_F(WebRtcVideoEngineTestFake, MultipleSendStreamsWithOneCapturer) {
// Test disabled because it drops frames when adapt-before-effects is turned
// off (turned off because it was exposing a crash - see bug 12250150). This is
// safe for now because this test exercises an unused feature.
// TODO(tpsiaki) reenable once adapt-before-effects is turned back on.
TEST_F(WebRtcVideoEngineTestFake, DISABLED_MultipleSendStreamsWithOneCapturer) {
EXPECT_TRUE(SetupEngine());
// Start the capturer

View File

@ -1655,7 +1655,6 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine)
engine,
engine->CreateMediaVoiceChannel()),
send_bw_setting_(false),
send_autobw_(false),
send_bw_bps_(0),
options_(),
dtmf_allowed_(false),
@ -2023,7 +2022,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
send_codec_.reset(new webrtc::CodecInst(send_codec));
if (send_bw_setting_) {
SetSendBandwidthInternal(send_autobw_, send_bw_bps_);
SetSendBandwidthInternal(send_bw_bps_);
}
return true;
@ -2928,18 +2927,23 @@ bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) {
return true;
}
bool WebRtcVoiceMediaChannel::SetSendBandwidth(bool autobw, int bps) {
LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidth.";
send_bw_setting_ = true;
send_autobw_ = autobw;
send_bw_bps_ = bps;
return SetSendBandwidthInternal(send_autobw_, send_bw_bps_);
bool WebRtcVoiceMediaChannel::SetStartSendBandwidth(int bps) {
// TODO(andresp): Add support for setting an independent start bandwidth when
// bandwidth estimation is enabled for voice engine.
return false;
}
bool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(bool autobw, int bps) {
LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidthInternal.";
bool WebRtcVoiceMediaChannel::SetMaxSendBandwidth(int bps) {
LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidth.";
return SetSendBandwidthInternal(bps);
}
bool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(int bps) {
LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBandwidthInternal.";
send_bw_setting_ = true;
send_bw_bps_ = bps;
if (!send_codec_) {
LOG(LS_INFO) << "The send codec has not been set up yet. "
@ -2948,7 +2952,9 @@ bool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(bool autobw, int bps) {
}
// Bandwidth is auto by default.
if (autobw || bps <= 0)
// TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by
// SetMaxSendBandwith(0), the second call removes the previous limit.
if (bps <= 0)
return true;
webrtc::CodecInst codec = *send_codec_;

View File

@ -365,7 +365,8 @@ class WebRtcVoiceMediaChannel
const talk_base::PacketTime& packet_time);
virtual void OnReadyToSend(bool ready) {}
virtual bool MuteStream(uint32 ssrc, bool on);
virtual bool SetSendBandwidth(bool autobw, int bps);
virtual bool SetStartSendBandwidth(int bps);
virtual bool SetMaxSendBandwidth(int bps);
virtual bool GetStats(VoiceMediaInfo* info);
// Gets last reported error from WebRtc voice engine. This should be only
// called in response a failure.
@ -411,7 +412,7 @@ class WebRtcVoiceMediaChannel
return channel_id == voe_channel();
}
bool SetSendCodecs(int channel, const std::vector<AudioCodec>& codecs);
bool SetSendBandwidthInternal(bool autobw, int bps);
bool SetSendBandwidthInternal(int bps);
talk_base::scoped_ptr<WebRtcSoundclipStream> ringback_tone_;
std::set<int> ringback_channels_; // channels playing ringback
@ -419,7 +420,6 @@ class WebRtcVoiceMediaChannel
std::vector<AudioCodec> send_codecs_;
talk_base::scoped_ptr<webrtc::CodecInst> send_codec_;
bool send_bw_setting_;
bool send_autobw_;
int send_bw_bps_;
AudioOptions options_;
bool dtmf_allowed_;

View File

@ -201,39 +201,26 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
// Test that send bandwidth is set correctly.
// |codec| is the codec under test.
// |default_bitrate| is the default bitrate for the codec.
// |auto_bitrate| is a parameter to set to SetSendBandwidth().
// |desired_bitrate| is a parameter to set to SetSendBandwidth().
// |expected_result| is expected results from SetSendBandwidth().
// |max_bitrate| is a parameter to set to SetMaxSendBandwidth().
// |expected_result| is the expected result from SetMaxSendBandwidth().
// |expected_bitrate| is the expected audio bitrate afterward.
void TestSendBandwidth(const cricket::AudioCodec& codec,
int default_bitrate,
bool auto_bitrate,
int desired_bitrate,
bool expected_result) {
int max_bitrate,
bool expected_result,
int expected_bitrate) {
int channel_num = voe_.GetLastChannel();
std::vector<cricket::AudioCodec> codecs;
codecs.push_back(codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
bool result = channel_->SetSendBandwidth(auto_bitrate, desired_bitrate);
bool result = channel_->SetMaxSendBandwidth(max_bitrate);
EXPECT_EQ(expected_result, result);
webrtc::CodecInst temp_codec;
EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec));
if (result) {
// If SetSendBandwidth() returns true then bitrate is set correctly.
if (auto_bitrate) {
EXPECT_EQ(default_bitrate, temp_codec.rate);
} else {
EXPECT_EQ(desired_bitrate, temp_codec.rate);
}
} else {
// If SetSendBandwidth() returns false then bitrate is set to the
// default value.
EXPECT_EQ(default_bitrate, temp_codec.rate);
}
EXPECT_EQ(expected_bitrate, temp_codec.rate);
}
@ -575,47 +562,67 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthAuto) {
EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
// Test that when autobw is true, bitrate is kept as the default
// value. autobw is true for the following tests.
// Test that when autobw is enabled, bitrate is kept as the default
// value. autobw is enabled for the following tests because the target
// bitrate is <= 0.
// ISAC, default bitrate == 32000.
TestSendBandwidth(kIsacCodec, 32000, true, 96000, true);
TestSendBandwidth(kIsacCodec, 0, true, 32000);
// PCMU, default bitrate == 64000.
TestSendBandwidth(kPcmuCodec, 64000, true, 96000, true);
TestSendBandwidth(kPcmuCodec, -1, true, 64000);
// CELT, default bitrate == 64000.
TestSendBandwidth(kCeltCodec, 64000, true, 96000, true);
TestSendBandwidth(kCeltCodec, 0, true, 64000);
// opus, default bitrate == 64000.
TestSendBandwidth(kOpusCodec, 64000, true, 96000, true);
TestSendBandwidth(kOpusCodec, -1, true, 64000);
}
TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCaller) {
TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthMultiRateAsCaller) {
EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
// Test that we can set bitrate if a multi-rate codec is used.
// autobw is false for the following tests.
// Test that the bitrate of a multi-rate codec is always the maximum.
// ISAC, default bitrate == 32000.
TestSendBandwidth(kIsacCodec, 32000, false, 128000, true);
TestSendBandwidth(kIsacCodec, 128000, true, 128000);
TestSendBandwidth(kIsacCodec, 16000, true, 16000);
// CELT, default bitrate == 64000.
TestSendBandwidth(kCeltCodec, 64000, false, 96000, true);
TestSendBandwidth(kCeltCodec, 96000, true, 96000);
TestSendBandwidth(kCeltCodec, 32000, true, 32000);
// opus, default bitrate == 64000.
TestSendBandwidth(kOpusCodec, 64000, false, 96000, true);
TestSendBandwidth(kOpusCodec, 96000, true, 96000);
TestSendBandwidth(kOpusCodec, 48000, true, 48000);
}
TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCallee) {
TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthFixedRateAsCaller) {
EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
// Test that we can only set a maximum bitrate for a fixed-rate codec
// if it's bigger than the fixed rate.
// PCMU, fixed bitrate == 64000.
TestSendBandwidth(kPcmuCodec, 0, true, 64000);
TestSendBandwidth(kPcmuCodec, 1, false, 64000);
TestSendBandwidth(kPcmuCodec, 128000, true, 64000);
TestSendBandwidth(kPcmuCodec, 32000, false, 64000);
TestSendBandwidth(kPcmuCodec, 64000, true, 64000);
TestSendBandwidth(kPcmuCodec, 63999, false, 64000);
TestSendBandwidth(kPcmuCodec, 64001, true, 64000);
}
TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthMultiRateAsCallee) {
EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
channel_ = engine_.CreateChannel();
EXPECT_TRUE(channel_ != NULL);
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
int desired_bitrate = 128000;
EXPECT_TRUE(channel_->SetSendBandwidth(false, desired_bitrate));
EXPECT_TRUE(channel_->SetMaxSendBandwidth(desired_bitrate));
EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrc1)));
@ -629,7 +636,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCallee) {
// Test that bitrate cannot be set for CBR codecs.
// Bitrate is ignored if it is higher than the fixed bitrate.
// Bitrate less then the fixed bitrate is an error.
TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedCbr) {
TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthCbr) {
EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
@ -642,10 +649,10 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedCbr) {
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec));
EXPECT_EQ(64000, codec.rate);
EXPECT_TRUE(channel_->SetSendBandwidth(false, 128000));
EXPECT_TRUE(channel_->SetMaxSendBandwidth(128000));
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec));
EXPECT_EQ(64000, codec.rate);
EXPECT_FALSE(channel_->SetSendBandwidth(false, 128));
EXPECT_FALSE(channel_->SetMaxSendBandwidth(128));
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec));
EXPECT_EQ(64000, codec.rate);
}

View File

@ -66,8 +66,8 @@ class DtlsTransport : public Base {
return true;
}
virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl*
channel) {
virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl* channel,
std::string* error_desc) {
talk_base::SSLFingerprint* local_fp =
Base::local_description()->identity_fingerprint.get();
@ -79,30 +79,36 @@ class DtlsTransport : public Base {
identity_));
ASSERT(local_fp_tmp.get() != NULL);
if (!(*local_fp_tmp == *local_fp)) {
LOG(LS_WARNING) << "Local fingerprint does not match identity";
return false;
std::ostringstream desc;
desc << "Local fingerprint does not match identity. Expected: ";
desc << local_fp_tmp->ToString();
desc << " Got: " << local_fp->ToString();
return BadTransportDescription(desc.str(), error_desc);
}
} else {
LOG(LS_WARNING)
<< "Local fingerprint provided but no identity available";
return false;
return BadTransportDescription(
"Local fingerprint provided but no identity available.",
error_desc);
}
} else {
identity_ = NULL;
}
if (!channel->SetLocalIdentity(identity_))
return false;
if (!channel->SetLocalIdentity(identity_)) {
return BadTransportDescription("Failed to set local identity.",
error_desc);
}
// Apply the description in the base class.
return Base::ApplyLocalTransportDescription_w(channel);
return Base::ApplyLocalTransportDescription_w(channel, error_desc);
}
virtual bool NegotiateTransportDescription_w(ContentAction local_role) {
virtual bool NegotiateTransportDescription_w(ContentAction local_role,
std::string* error_desc) {
if (!Base::local_description() || !Base::remote_description()) {
LOG(LS_INFO) << "Local and Remote description must be set before "
<< "transport descriptions are negotiated";
return false;
const std::string msg = "Local and Remote description must be set before "
"transport descriptions are negotiated";
return BadTransportDescription(msg, error_desc);
}
talk_base::SSLFingerprint* local_fp =
@ -144,8 +150,9 @@ class DtlsTransport : public Base {
bool is_remote_server = false;
if (local_role == CA_OFFER) {
if (local_connection_role != CONNECTIONROLE_ACTPASS) {
LOG(LS_ERROR) << "Offerer must use actpass value for setup attribute";
return false;
return BadTransportDescription(
"Offerer must use actpass value for setup attribute.",
error_desc);
}
if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
@ -153,25 +160,28 @@ class DtlsTransport : public Base {
remote_connection_role == CONNECTIONROLE_NONE) {
is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
} else {
LOG(LS_ERROR) << "Answerer must use either active or passive value "
<< "for setup attribute";
return false;
const std::string msg =
"Answerer must use either active or passive value "
"for setup attribute.";
return BadTransportDescription(msg, error_desc);
}
// If remote is NONE or ACTIVE it will act as client.
} else {
if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
remote_connection_role != CONNECTIONROLE_NONE) {
LOG(LS_ERROR) << "Offerer must use actpass value for setup attribute";
return false;
return BadTransportDescription(
"Offerer must use actpass value for setup attribute.",
error_desc);
}
if (local_connection_role == CONNECTIONROLE_ACTIVE ||
local_connection_role == CONNECTIONROLE_PASSIVE) {
is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
} else {
LOG(LS_ERROR) << "Answerer must use either active or passive value "
<< "for setup attribute";
return false;
const std::string msg =
"Answerer must use either active or passive value "
"for setup attribute.";
return BadTransportDescription(msg, error_desc);
}
// If local is passive, local will act as server.
@ -181,9 +191,9 @@ class DtlsTransport : public Base {
talk_base::SSL_SERVER;
} else if (local_fp && (local_role == CA_ANSWER)) {
LOG(LS_ERROR)
<< "Local fingerprint supplied when caller didn't offer DTLS";
return false;
return BadTransportDescription(
"Local fingerprint supplied when caller didn't offer DTLS.",
error_desc);
} else {
// We are not doing DTLS
remote_fingerprint_.reset(new talk_base::SSLFingerprint(
@ -191,7 +201,7 @@ class DtlsTransport : public Base {
}
// Now run the negotiation for the base class.
return Base::NegotiateTransportDescription_w(local_role);
return Base::NegotiateTransportDescription_w(local_role, error_desc);
}
virtual DtlsTransportChannelWrapper* CreateTransportChannel(int component) {
@ -216,12 +226,13 @@ class DtlsTransport : public Base {
private:
virtual bool ApplyNegotiatedTransportDescription_w(
TransportChannelImpl* channel) {
TransportChannelImpl* channel,
std::string* error_desc) {
// Set ssl role. Role must be set before fingerprint is applied, which
// initiates DTLS setup.
if (!channel->SetSslRole(secure_role_)) {
LOG(LS_INFO) << "Failed to set ssl role for the channel.";
return false;
return BadTransportDescription("Failed to set ssl role for the channel.",
error_desc);
}
// Apply remote fingerprint.
if (!channel->SetRemoteFingerprint(
@ -229,9 +240,10 @@ class DtlsTransport : public Base {
reinterpret_cast<const uint8 *>(remote_fingerprint_->
digest.data()),
remote_fingerprint_->digest.length())) {
return false;
return BadTransportDescription("Failed to apply remote fingerprint.",
error_desc);
}
return Base::ApplyNegotiatedTransportDescription_w(channel);
return Base::ApplyNegotiatedTransportDescription_w(channel, error_desc);
}
talk_base::SSLIdentity* identity_;

View File

@ -185,14 +185,14 @@ class DtlsTestClient : public sigslot::has_slots<> {
// content action is CA_ANSWER.
if (action == cricket::CA_OFFER) {
ASSERT_TRUE(transport_->SetLocalTransportDescription(
local_desc, cricket::CA_OFFER));
local_desc, cricket::CA_OFFER, NULL));
ASSERT_EQ(expect_success, transport_->SetRemoteTransportDescription(
remote_desc, cricket::CA_ANSWER));
remote_desc, cricket::CA_ANSWER, NULL));
} else {
ASSERT_TRUE(transport_->SetRemoteTransportDescription(
remote_desc, cricket::CA_OFFER));
remote_desc, cricket::CA_OFFER, NULL));
ASSERT_EQ(expect_success, transport_->SetLocalTransportDescription(
local_desc, cricket::CA_ANSWER));
local_desc, cricket::CA_ANSWER, NULL));
}
negotiated_dtls_ = (local_identity && remote_identity);
}

View File

@ -277,21 +277,29 @@ void TransportProxy::SetIceRole(IceRole role) {
}
bool TransportProxy::SetLocalTransportDescription(
const TransportDescription& description, ContentAction action) {
const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
// If this is an answer, finalize the negotiation.
if (action == CA_ANSWER) {
CompleteNegotiation();
}
return transport_->get()->SetLocalTransportDescription(description, action);
return transport_->get()->SetLocalTransportDescription(description,
action,
error_desc);
}
bool TransportProxy::SetRemoteTransportDescription(
const TransportDescription& description, ContentAction action) {
const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
// If this is an answer, finalize the negotiation.
if (action == CA_ANSWER) {
CompleteNegotiation();
}
return transport_->get()->SetRemoteTransportDescription(description, action);
return transport_->get()->SetRemoteTransportDescription(description,
action,
error_desc);
}
void TransportProxy::OnSignalingReady() {
@ -418,16 +426,22 @@ bool BaseSession::SetIdentity(talk_base::SSLIdentity* identity) {
}
bool BaseSession::PushdownTransportDescription(ContentSource source,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
if (source == CS_LOCAL) {
return PushdownLocalTransportDescription(local_description_, action);
return PushdownLocalTransportDescription(local_description_,
action,
error_desc);
}
return PushdownRemoteTransportDescription(remote_description_, action);
return PushdownRemoteTransportDescription(remote_description_,
action,
error_desc);
}
bool BaseSession::PushdownLocalTransportDescription(
const SessionDescription* sdesc,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
// Update the Transports with the right information, and trigger them to
// start connecting.
for (TransportMap::iterator iter = transports_.begin();
@ -438,7 +452,8 @@ bool BaseSession::PushdownLocalTransportDescription(
bool ret = GetTransportDescription(
sdesc, iter->second->content_name(), &tdesc);
if (ret) {
if (!iter->second->SetLocalTransportDescription(tdesc, action)) {
if (!iter->second->SetLocalTransportDescription(tdesc, action,
error_desc)) {
return false;
}
@ -451,7 +466,8 @@ bool BaseSession::PushdownLocalTransportDescription(
bool BaseSession::PushdownRemoteTransportDescription(
const SessionDescription* sdesc,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
// Update the Transports with the right information.
for (TransportMap::iterator iter = transports_.begin();
iter != transports_.end(); ++iter) {
@ -462,7 +478,8 @@ bool BaseSession::PushdownRemoteTransportDescription(
bool ret = GetTransportDescription(
sdesc, iter->second->content_name(), &tdesc);
if (ret) {
if (!iter->second->SetRemoteTransportDescription(tdesc, action)) {
if (!iter->second->SetRemoteTransportDescription(tdesc, action,
error_desc)) {
return false;
}
}
@ -611,10 +628,11 @@ void BaseSession::SetState(State state) {
SignalNewDescription();
}
void BaseSession::SetError(Error error) {
void BaseSession::SetError(Error error, const std::string& error_desc) {
ASSERT(signaling_thread_->IsCurrent());
if (error != error_) {
error_ = error;
error_desc_ = error_desc;
SignalError(this, error);
}
}
@ -856,7 +874,7 @@ void BaseSession::OnMessage(talk_base::Message *pmsg) {
switch (pmsg->message_id) {
case MSG_TIMEOUT:
// Session timeout has occured.
SetError(ERROR_TIME);
SetError(ERROR_TIME, "Session timeout has occured.");
break;
case MSG_STATE:
@ -925,7 +943,7 @@ bool Session::Initiate(const std::string &to,
// the TransportDescriptions.
SpeculativelyConnectAllTransportChannels();
PushdownTransportDescription(CS_LOCAL, CA_OFFER);
PushdownTransportDescription(CS_LOCAL, CA_OFFER, NULL);
SetState(Session::STATE_SENTINITIATE);
return true;
}
@ -946,7 +964,7 @@ bool Session::Accept(const SessionDescription* sdesc) {
return false;
}
// TODO(juberti): Add BUNDLE support to transport-info messages.
PushdownTransportDescription(CS_LOCAL, CA_ANSWER);
PushdownTransportDescription(CS_LOCAL, CA_ANSWER, NULL);
MaybeEnableMuxingSupport(); // Enable transport channel mux if supported.
SetState(Session::STATE_SENTACCEPT);
return true;
@ -1261,8 +1279,10 @@ void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
if (!OnRedirectError(redirect, &error)) {
// TODO: Should we send a message back? The standard
// says nothing about it.
LOG(LS_ERROR) << "Failed to redirect: " << error.text;
SetError(ERROR_RESPONSE);
std::ostringstream desc;
desc << "Failed to redirect: " << error.text;
LOG(LS_ERROR) << desc.str();
SetError(ERROR_RESPONSE, desc.str());
}
return;
}
@ -1290,7 +1310,7 @@ void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
} else if ((error_type != "continue") && (error_type != "wait")) {
// We do not set an error if the other side said it is okay to continue
// (possibly after waiting). These errors can be ignored.
SetError(ERROR_RESPONSE);
SetError(ERROR_RESPONSE, "");
}
}
@ -1318,7 +1338,7 @@ bool Session::OnInitiateMessage(const SessionMessage& msg,
init.transports,
init.groups));
// Updating transport with TransportDescription.
PushdownTransportDescription(CS_REMOTE, CA_OFFER);
PushdownTransportDescription(CS_REMOTE, CA_OFFER, NULL);
SetState(STATE_RECEIVEDINITIATE);
// Users of Session may listen to state change and call Reject().
@ -1352,7 +1372,7 @@ bool Session::OnAcceptMessage(const SessionMessage& msg, MessageError* error) {
accept.transports,
accept.groups));
// Updating transport with TransportDescription.
PushdownTransportDescription(CS_REMOTE, CA_ANSWER);
PushdownTransportDescription(CS_REMOTE, CA_ANSWER, NULL);
MaybeEnableMuxingSupport(); // Enable transport channel mux if supported.
SetState(STATE_RECEIVEDACCEPT);
@ -1496,8 +1516,8 @@ bool Session::CheckState(State expected, MessageError* error) {
return true;
}
void Session::SetError(Error error) {
BaseSession::SetError(error);
void Session::SetError(Error error, const std::string& error_desc) {
BaseSession::SetError(error, error_desc);
if (error != ERROR_NONE)
signaling_thread()->Post(this, MSG_ERROR);
}

View File

@ -145,9 +145,11 @@ class TransportProxy : public sigslot::has_slots<>,
void SetIceRole(IceRole role);
void SetIdentity(talk_base::SSLIdentity* identity);
bool SetLocalTransportDescription(const TransportDescription& description,
ContentAction action);
ContentAction action,
std::string* error_desc);
bool SetRemoteTransportDescription(const TransportDescription& description,
ContentAction action);
ContentAction action,
std::string* error_desc);
void OnSignalingReady();
bool OnRemoteCandidates(const Candidates& candidates, std::string* error);
@ -327,13 +329,15 @@ class BaseSession : public sigslot::has_slots<>,
// Returns the last error in the session. See the enum above for details.
// Each time the an error occurs, we will fire this signal.
Error error() const { return error_; }
const std::string& error_desc() const { return error_desc_; }
sigslot::signal2<BaseSession* , Error> SignalError;
// Updates the state, signaling if necessary.
virtual void SetState(State state);
// Updates the error state, signaling if necessary.
virtual void SetError(Error error);
// TODO(ronghuawu): remove the SetError method that doesn't take |error_desc|.
virtual void SetError(Error error, const std::string& error_desc);
// Fired when the remote description is updated, with the updated
// contents.
@ -384,7 +388,8 @@ class BaseSession : public sigslot::has_slots<>,
bool SetIdentity(talk_base::SSLIdentity* identity);
bool PushdownTransportDescription(ContentSource source,
ContentAction action);
ContentAction action,
std::string* error_desc);
void set_initiator(bool initiator) { initiator_ = initiator; }
const TransportMap& transport_proxies() const { return transports_; }
@ -466,13 +471,16 @@ class BaseSession : public sigslot::has_slots<>,
protected:
State state_;
Error error_;
std::string error_desc_;
private:
// Helper methods to push local and remote transport descriptions.
bool PushdownLocalTransportDescription(
const SessionDescription* sdesc, ContentAction action);
const SessionDescription* sdesc, ContentAction action,
std::string* error_desc);
bool PushdownRemoteTransportDescription(
const SessionDescription* sdesc, ContentAction action);
const SessionDescription* sdesc, ContentAction action,
std::string* error_desc);
bool IsCandidateAllocationDone() const;
void MaybeCandidateAllocationDone();
@ -553,7 +561,7 @@ class Session : public BaseSession {
}
// Updates the error state, signaling if necessary.
virtual void SetError(Error error);
virtual void SetError(Error error, const std::string& error_desc);
// When the session needs to send signaling messages, it beings by requesting
// signaling. The client should handle this by calling OnSignalingReady once

View File

@ -73,6 +73,33 @@ struct ChannelParams : public talk_base::MessageData {
Candidate* candidate;
};
static std::string IceProtoToString(TransportProtocol proto) {
std::string proto_str;
switch (proto) {
case ICEPROTO_GOOGLE:
proto_str = "gice";
break;
case ICEPROTO_HYBRID:
proto_str = "hybrid";
break;
case ICEPROTO_RFC5245:
proto_str = "ice";
break;
default:
ASSERT(false);
break;
}
return proto_str;
}
bool BadTransportDescription(const std::string& desc, std::string* err_desc) {
if (err_desc) {
*err_desc = desc;
}
LOG(LS_ERROR) << desc;
return false;
}
Transport::Transport(talk_base::Thread* signaling_thread,
talk_base::Thread* worker_thread,
const std::string& content_name,
@ -131,15 +158,21 @@ bool Transport::GetRemoteCertificate_w(talk_base::SSLCertificate** cert) {
}
bool Transport::SetLocalTransportDescription(
const TransportDescription& description, ContentAction action) {
const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
return worker_thread_->Invoke<bool>(Bind(
&Transport::SetLocalTransportDescription_w, this, description, action));
&Transport::SetLocalTransportDescription_w, this,
description, action, error_desc));
}
bool Transport::SetRemoteTransportDescription(
const TransportDescription& description, ContentAction action) {
const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
return worker_thread_->Invoke<bool>(Bind(
&Transport::SetRemoteTransportDescription_w, this, description, action));
&Transport::SetRemoteTransportDescription_w, this,
description, action, error_desc));
}
TransportChannelImpl* Transport::CreateChannel(int component) {
@ -176,10 +209,12 @@ TransportChannelImpl* Transport::CreateChannel_w(int component) {
impl->SetIceRole(ice_role_);
impl->SetIceTiebreaker(tiebreaker_);
if (local_description_) {
ApplyLocalTransportDescription_w(impl);
// TODO(ronghuawu): Change CreateChannel_w to be able to return error since
// below Apply**Description_w calls can fail.
ApplyLocalTransportDescription_w(impl, NULL);
if (remote_description_) {
ApplyRemoteTransportDescription_w(impl);
ApplyNegotiatedTransportDescription_w(impl);
ApplyRemoteTransportDescription_w(impl, NULL);
ApplyNegotiatedTransportDescription_w(impl, NULL);
}
}
@ -276,7 +311,7 @@ void Transport::ConnectChannels_w() {
talk_base::CreateRandomString(ICE_PWD_LENGTH),
ICEMODE_FULL, CONNECTIONROLE_NONE, NULL,
Candidates());
SetLocalTransportDescription_w(desc, CA_OFFER);
SetLocalTransportDescription_w(desc, CA_OFFER, NULL);
}
CallChannels_w(&TransportChannelImpl::Connect);
@ -606,63 +641,70 @@ void Transport::SetRemoteIceMode_w(IceMode mode) {
}
bool Transport::SetLocalTransportDescription_w(
const TransportDescription& desc, ContentAction action) {
const TransportDescription& desc,
ContentAction action,
std::string* error_desc) {
bool ret = true;
talk_base::CritScope cs(&crit_);
local_description_.reset(new TransportDescription(desc));
for (ChannelMap::iterator iter = channels_.begin();
iter != channels_.end(); ++iter) {
ret &= ApplyLocalTransportDescription_w(iter->second.get());
ret &= ApplyLocalTransportDescription_w(iter->second.get(), error_desc);
}
if (!ret)
return false;
// If PRANSWER/ANSWER is set, we should decide transport protocol type.
if (action == CA_PRANSWER || action == CA_ANSWER) {
ret &= NegotiateTransportDescription_w(action);
ret &= NegotiateTransportDescription_w(action, error_desc);
}
return ret;
}
bool Transport::SetRemoteTransportDescription_w(
const TransportDescription& desc, ContentAction action) {
const TransportDescription& desc,
ContentAction action,
std::string* error_desc) {
bool ret = true;
talk_base::CritScope cs(&crit_);
remote_description_.reset(new TransportDescription(desc));
for (ChannelMap::iterator iter = channels_.begin();
iter != channels_.end(); ++iter) {
ret &= ApplyRemoteTransportDescription_w(iter->second.get());
ret &= ApplyRemoteTransportDescription_w(iter->second.get(), error_desc);
}
// If PRANSWER/ANSWER is set, we should decide transport protocol type.
if (action == CA_PRANSWER || action == CA_ANSWER) {
ret = NegotiateTransportDescription_w(CA_OFFER);
ret = NegotiateTransportDescription_w(CA_OFFER, error_desc);
}
return ret;
}
bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch) {
bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch,
std::string* error_desc) {
ch->SetIceCredentials(local_description_->ice_ufrag,
local_description_->ice_pwd);
return true;
}
bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch) {
bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch,
std::string* error_desc) {
ch->SetRemoteIceCredentials(remote_description_->ice_ufrag,
remote_description_->ice_pwd);
return true;
}
bool Transport::ApplyNegotiatedTransportDescription_w(
TransportChannelImpl* channel) {
TransportChannelImpl* channel, std::string* error_desc) {
channel->SetIceProtocolType(protocol_);
channel->SetRemoteIceMode(remote_ice_mode_);
return true;
}
bool Transport::NegotiateTransportDescription_w(ContentAction local_role) {
bool Transport::NegotiateTransportDescription_w(ContentAction local_role,
std::string* error_desc) {
// TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into
// P2PTransport.
const TransportDescription* offer;
@ -690,7 +732,12 @@ bool Transport::NegotiateTransportDescription_w(ContentAction local_role) {
// answer must be treated as error.
if ((offer_proto == ICEPROTO_GOOGLE || offer_proto == ICEPROTO_RFC5245) &&
(offer_proto != answer_proto)) {
return false;
std::ostringstream desc;
desc << "Offer and answer protocol mismatch: "
<< IceProtoToString(offer_proto)
<< " vs "
<< IceProtoToString(answer_proto);
return BadTransportDescription(desc.str(), error_desc);
}
protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto;
@ -712,7 +759,7 @@ bool Transport::NegotiateTransportDescription_w(ContentAction local_role) {
for (ChannelMap::iterator iter = channels_.begin();
iter != channels_.end();
++iter) {
if (!ApplyNegotiatedTransportDescription_w(iter->second.get()))
if (!ApplyNegotiatedTransportDescription_w(iter->second.get(), error_desc))
return false;
}
return true;

View File

@ -187,6 +187,8 @@ struct TransportStats {
TransportChannelStatsList channel_stats;
};
bool BadTransportDescription(const std::string& desc, std::string* err_desc);
class Transport : public talk_base::MessageHandler,
public sigslot::has_slots<> {
public:
@ -270,11 +272,13 @@ class Transport : public talk_base::MessageHandler,
// Set the local TransportDescription to be used by TransportChannels.
// This should be called before ConnectChannels().
bool SetLocalTransportDescription(const TransportDescription& description,
ContentAction action);
ContentAction action,
std::string* error_desc);
// Set the remote TransportDescription to be used by TransportChannels.
bool SetRemoteTransportDescription(const TransportDescription& description,
ContentAction action);
ContentAction action,
std::string* error_desc);
// Tells all current and future channels to start connecting. When the first
// channel begins connecting, the following signal is raised.
@ -362,25 +366,27 @@ class Transport : public talk_base::MessageHandler,
// Pushes down the transport parameters from the local description, such
// as the ICE ufrag and pwd.
// Derived classes can override, but must call the base as well.
virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl*
channel);
virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl* channel,
std::string* error_desc);
// Pushes down remote ice credentials from the remote description to the
// transport channel.
virtual bool ApplyRemoteTransportDescription_w(TransportChannelImpl* ch);
virtual bool ApplyRemoteTransportDescription_w(TransportChannelImpl* ch,
std::string* error_desc);
// Negotiates the transport parameters based on the current local and remote
// transport description, such at the version of ICE to use, and whether DTLS
// should be activated.
// Derived classes can negotiate their specific parameters here, but must call
// the base as well.
virtual bool NegotiateTransportDescription_w(ContentAction local_role);
virtual bool NegotiateTransportDescription_w(ContentAction local_role,
std::string* error_desc);
// Pushes down the transport parameters obtained via negotiation.
// Derived classes can set their specific parameters here, but must call the
// base as well.
virtual bool ApplyNegotiatedTransportDescription_w(
TransportChannelImpl* channel);
TransportChannelImpl* channel, std::string* error_desc);
virtual bool GetSslRole_w(talk_base::SSLRole* ssl_role) const {
return false;
@ -468,9 +474,11 @@ class Transport : public talk_base::MessageHandler,
void SetIceRole_w(IceRole role);
void SetRemoteIceMode_w(IceMode mode);
bool SetLocalTransportDescription_w(const TransportDescription& desc,
ContentAction action);
ContentAction action,
std::string* error_desc);
bool SetRemoteTransportDescription_w(const TransportDescription& desc,
ContentAction action);
ContentAction action,
std::string* error_desc);
bool GetStats_w(TransportStats* infos);
bool GetRemoteCertificate_w(talk_base::SSLCertificate** cert);

View File

@ -147,7 +147,8 @@ TEST_F(TransportTest, TestChannelIceParameters) {
cricket::TransportDescription local_desc(
cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
cricket::CA_OFFER));
cricket::CA_OFFER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
EXPECT_TRUE(SetupChannel());
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
@ -158,7 +159,8 @@ TEST_F(TransportTest, TestChannelIceParameters) {
cricket::TransportDescription remote_desc(
cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
cricket::CA_ANSWER));
cricket::CA_ANSWER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
EXPECT_EQ(99U, channel_->IceTiebreaker());
EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
@ -178,11 +180,13 @@ TEST_F(TransportTest, TestSetRemoteIceLiteInOffer) {
kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
cricket::CONNECTIONROLE_ACTPASS, NULL, cricket::Candidates());
ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
cricket::CA_OFFER));
cricket::CA_OFFER,
NULL));
cricket::TransportDescription local_desc(
cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
cricket::CA_ANSWER));
cricket::CA_ANSWER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
EXPECT_TRUE(SetupChannel());
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
@ -195,7 +199,8 @@ TEST_F(TransportTest, TestSetRemoteIceLiteInAnswer) {
cricket::TransportDescription local_desc(
cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
cricket::CA_OFFER));
cricket::CA_OFFER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
EXPECT_TRUE(SetupChannel());
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
@ -206,7 +211,8 @@ TEST_F(TransportTest, TestSetRemoteIceLiteInAnswer) {
kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
cricket::CONNECTIONROLE_NONE, NULL, cricket::Candidates());
ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
cricket::CA_ANSWER));
cricket::CA_ANSWER,
NULL));
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
// After receiving remote description with ICEMODE_LITE, channel should
// have mode set to ICEMODE_LITE.

View File

@ -195,6 +195,9 @@ TurnPort::~TurnPort() {
while (!entries_.empty()) {
DestroyEntry(entries_.front()->address());
}
if (resolver_) {
resolver_->Destroy(false);
}
}
void TurnPort::PrepareAddress() {

View File

@ -523,7 +523,7 @@ bool Call::StartScreencast(Session* session,
VideoContentDescription* video = CreateVideoStreamUpdate(stream);
// TODO(pthatcher): Wait until view request before sending video.
video_channel->SetLocalContent(video, CA_UPDATE);
video_channel->SetLocalContent(video, CA_UPDATE, NULL);
SendVideoStreamUpdate(session, video);
return true;
}
@ -546,7 +546,7 @@ bool Call::StopScreencast(Session* session,
// No ssrcs
VideoContentDescription* video = CreateVideoStreamUpdate(stream);
video_channel->SetLocalContent(video, CA_UPDATE);
video_channel->SetLocalContent(video, CA_UPDATE, NULL);
SendVideoStreamUpdate(session, video);
return true;
}
@ -870,9 +870,11 @@ void Call::OnRemoteDescriptionUpdate(BaseSession* base_session,
bool Call::UpdateVoiceChannelRemoteContent(
Session* session, const AudioContentDescription* audio) {
VoiceChannel* voice_channel = GetVoiceChannel(session);
if (!voice_channel->SetRemoteContent(audio, CA_UPDATE)) {
LOG(LS_ERROR) << "Failure in audio SetRemoteContent with CA_UPDATE";
session->SetError(BaseSession::ERROR_CONTENT);
if (!voice_channel->SetRemoteContent(audio, CA_UPDATE, NULL)) {
const std::string error_desc =
"Failure in audio SetRemoteContent with CA_UPDATE";
LOG(LS_ERROR) << error_desc;
session->SetError(BaseSession::ERROR_CONTENT, error_desc);
return false;
}
return true;
@ -881,9 +883,11 @@ bool Call::UpdateVoiceChannelRemoteContent(
bool Call::UpdateVideoChannelRemoteContent(
Session* session, const VideoContentDescription* video) {
VideoChannel* video_channel = GetVideoChannel(session);
if (!video_channel->SetRemoteContent(video, CA_UPDATE)) {
LOG(LS_ERROR) << "Failure in video SetRemoteContent with CA_UPDATE";
session->SetError(BaseSession::ERROR_CONTENT);
if (!video_channel->SetRemoteContent(video, CA_UPDATE, NULL)) {
const std::string error_desc =
"Failure in video SetRemoteContent with CA_UPDATE";
LOG(LS_ERROR) << error_desc;
session->SetError(BaseSession::ERROR_CONTENT, error_desc);
return false;
}
return true;
@ -892,9 +896,11 @@ bool Call::UpdateVideoChannelRemoteContent(
bool Call::UpdateDataChannelRemoteContent(
Session* session, const DataContentDescription* data) {
DataChannel* data_channel = GetDataChannel(session);
if (!data_channel->SetRemoteContent(data, CA_UPDATE)) {
LOG(LS_ERROR) << "Failure in data SetRemoteContent with CA_UPDATE";
session->SetError(BaseSession::ERROR_CONTENT);
if (!data_channel->SetRemoteContent(data, CA_UPDATE, NULL)) {
const std::string error_desc =
"Failure in data SetRemoteContent with CA_UPDATE";
LOG(LS_ERROR) << error_desc;
session->SetError(BaseSession::ERROR_CONTENT, error_desc);
return false;
}
return true;

View File

@ -60,7 +60,6 @@ enum {
MSG_REMOVESENDSTREAM,
MSG_SETRINGBACKTONE,
MSG_PLAYRINGBACKTONE,
MSG_SETMAXSENDBANDWIDTH,
MSG_ADDSCREENCAST,
MSG_REMOVESCREENCAST,
MSG_SENDINTRAFRAME,
@ -88,6 +87,17 @@ static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
static const int kAgcMinus10db = -10;
static void SetSessionError(BaseSession* session, BaseSession::Error error,
const std::string& error_desc) {
session->SetError(error, error_desc);
}
static void SafeSetError(const std::string& message, std::string* error_desc) {
if (error_desc) {
*error_desc = message;
}
}
// TODO(hellner): use the device manager for creation of screen capturers when
// the cl enabling it has landed.
class NullScreenCapturerFactory : public VideoChannel::ScreenCapturerFactory {
@ -103,13 +113,17 @@ VideoChannel::ScreenCapturerFactory* CreateScreenCapturerFactory() {
}
struct SetContentData : public talk_base::MessageData {
SetContentData(const MediaContentDescription* content, ContentAction action)
SetContentData(const MediaContentDescription* content,
ContentAction action,
std::string* error_desc)
: content(content),
action(action),
error_desc(error_desc),
result(false) {
}
const MediaContentDescription* content;
ContentAction action;
std::string* error_desc;
bool result;
};
@ -273,10 +287,13 @@ struct DataChannelErrorMessageData : public talk_base::MessageData {
};
struct SessionErrorMessageData : public talk_base::MessageData {
explicit SessionErrorMessageData(cricket::BaseSession::Error error)
: error_(error) {}
SessionErrorMessageData(cricket::BaseSession::Error error,
const std::string& error_desc)
: error_(error),
error_desc_(error_desc) {}
BaseSession::Error error_;
std::string error_desc_;
};
struct SsrcMessageData : public talk_base::MessageData {
@ -505,25 +522,21 @@ bool BaseChannel::RemoveSendStream(uint32 ssrc) {
}
bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
ContentAction action) {
SetContentData data(content, action);
ContentAction action,
std::string* error_desc) {
SetContentData data(content, action, error_desc);
Send(MSG_SETLOCALCONTENT, &data);
return data.result;
}
bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
ContentAction action) {
SetContentData data(content, action);
ContentAction action,
std::string* error_desc) {
SetContentData data(content, action, error_desc);
Send(MSG_SETREMOTECONTENT, &data);
return data.result;
}
bool BaseChannel::SetMaxSendBandwidth(int max_bandwidth) {
SetBandwidthData data(max_bandwidth);
Send(MSG_SETMAXSENDBANDWIDTH, &data);
return data.result;
}
void BaseChannel::StartConnectionMonitor(int cms) {
socket_monitor_.reset(new SocketMonitor(transport_channel_,
worker_thread(),
@ -857,10 +870,11 @@ void BaseChannel::OnNewLocalDescription(
GetFirstContent(session->local_description());
const MediaContentDescription* content_desc =
GetContentDescription(content_info);
std::string error_desc;
if (content_desc && content_info && !content_info->rejected &&
!SetLocalContent(content_desc, action)) {
!SetLocalContent(content_desc, action, &error_desc)) {
SetSessionError(session_, BaseSession::ERROR_CONTENT, error_desc);
LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
session->SetError(BaseSession::ERROR_CONTENT);
}
}
@ -870,10 +884,11 @@ void BaseChannel::OnNewRemoteDescription(
GetFirstContent(session->remote_description());
const MediaContentDescription* content_desc =
GetContentDescription(content_info);
std::string error_desc;
if (content_desc && content_info && !content_info->rejected &&
!SetRemoteContent(content_desc, action)) {
LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
session->SetError(BaseSession::ERROR_CONTENT);
!SetRemoteContent(content_desc, action, &error_desc)) {
SetSessionError(session_, BaseSession::ERROR_CONTENT, error_desc);
LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
}
}
@ -938,8 +953,9 @@ void BaseChannel::ChannelWritable_w() {
// If we're doing DTLS-SRTP, now is the time.
if (!was_ever_writable_ && ShouldSetupDtlsSrtp()) {
if (!SetupDtlsSrtp(false)) {
LOG(LS_ERROR) << "Couldn't finish DTLS-SRTP on RTP channel";
SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT);
const std::string error_desc =
"Couldn't set up DTLS-SRTP on RTP channel.";
SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT, error_desc);
// Sent synchronously.
signaling_thread()->Send(this, MSG_SESSION_ERROR, &data);
return;
@ -947,8 +963,9 @@ void BaseChannel::ChannelWritable_w() {
if (rtcp_transport_channel_) {
if (!SetupDtlsSrtp(true)) {
LOG(LS_ERROR) << "Couldn't finish DTLS-SRTP on RTCP channel";
SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT);
const std::string error_desc =
"Couldn't set up DTLS-SRTP on RTCP channel";
SessionErrorMessageData data(BaseSession::ERROR_TRANSPORT, error_desc);
// Sent synchronously.
signaling_thread()->Send(this, MSG_SESSION_ERROR, &data);
return;
@ -1085,62 +1102,69 @@ void BaseChannel::ChannelNotWritable_w() {
ChangeState();
}
// Sets the maximum video bandwidth for automatic bandwidth adjustment.
bool BaseChannel::SetMaxSendBandwidth_w(int max_bandwidth) {
return media_channel()->SetSendBandwidth(true, max_bandwidth);
}
// |dtls| will be set to true if DTLS is active for transport channel and
// crypto is empty.
bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
bool* dtls) {
bool* dtls,
std::string* error_desc) {
*dtls = transport_channel_->IsDtlsActive();
if (*dtls && !cryptos.empty()) {
LOG(LS_WARNING) << "Cryptos must be empty when DTLS is active.";
SafeSetError("Cryptos must be empty when DTLS is active.",
error_desc);
return false;
}
return true;
}
bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
ContentAction action, ContentSource src) {
ContentAction action,
ContentSource src,
std::string* error_desc) {
if (action == CA_UPDATE) {
// no crypto params.
return true;
}
bool ret = false;
bool dtls = false;
ret = CheckSrtpConfig(cryptos, &dtls);
ret = CheckSrtpConfig(cryptos, &dtls, error_desc);
if (!ret) {
return false;
}
switch (action) {
case CA_OFFER:
// If DTLS is already active on the channel, we could be renegotiating
// here. We don't update the srtp filter.
if (ret && !dtls) {
if (!dtls) {
ret = srtp_filter_.SetOffer(cryptos, src);
}
break;
case CA_PRANSWER:
// If we're doing DTLS-SRTP, we don't want to update the filter
// with an answer, because we already have SRTP parameters.
if (ret && !dtls) {
if (!dtls) {
ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
}
break;
case CA_ANSWER:
// If we're doing DTLS-SRTP, we don't want to update the filter
// with an answer, because we already have SRTP parameters.
if (ret && !dtls) {
if (!dtls) {
ret = srtp_filter_.SetAnswer(cryptos, src);
}
break;
case CA_UPDATE:
// no crypto params.
ret = true;
break;
default:
break;
}
return ret;
if (!ret) {
SafeSetError("Failed to setup SRTP filter.", error_desc);
return false;
}
return true;
}
bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
ContentSource src) {
ContentSource src,
std::string* error_desc) {
bool ret = false;
switch (action) {
case CA_OFFER:
@ -1162,17 +1186,21 @@ bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
default:
break;
}
if (!ret) {
SafeSetError("Failed to setup RTCP mux filter.", error_desc);
return false;
}
// |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
// CA_ANSWER, but we only want to tear down the RTCP transport channel if we
// received a final answer.
if (ret && rtcp_mux_filter_.IsActive()) {
if (rtcp_mux_filter_.IsActive()) {
// If the RTP transport is already writable, then so are we.
if (transport_channel_->writable()) {
ChannelWritable_w();
}
}
return ret;
return true;
}
bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
@ -1200,7 +1228,8 @@ bool BaseChannel::RemoveSendStream_w(uint32 ssrc) {
}
bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
action == CA_PRANSWER || action == CA_UPDATE))
return false;
@ -1217,15 +1246,18 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
local_streams_.push_back(*it);
LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
} else {
LOG(LS_INFO) << "Failed to add send stream ssrc: "
<< it->first_ssrc();
std::ostringstream desc;
desc << "Failed to add send stream ssrc: " << it->first_ssrc();
SafeSetError(desc.str(), error_desc);
return false;
}
} else if (stream_exist && !it->has_ssrcs()) {
if (!media_channel()->RemoveSendStream(existing_stream.first_ssrc())) {
LOG(LS_ERROR) << "Failed to remove send stream with ssrc "
<< it->first_ssrc() << ".";
return false;
std::ostringstream desc;
desc << "Failed to remove send stream with ssrc "
<< it->first_ssrc() << ".";
SafeSetError(desc.str(), error_desc);
return false;
}
RemoveStreamBySsrc(&local_streams_, existing_stream.first_ssrc());
} else {
@ -1242,8 +1274,10 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
it != local_streams_.end(); ++it) {
if (!GetStreamBySsrc(streams, it->first_ssrc(), NULL)) {
if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
LOG(LS_ERROR) << "Failed to remove send stream with ssrc "
<< it->first_ssrc() << ".";
std::ostringstream desc;
desc << "Failed to remove send stream with ssrc "
<< it->first_ssrc() << ".";
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
@ -1255,7 +1289,9 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
if (media_channel()->AddSendStream(*it)) {
LOG(LS_INFO) << "Add send ssrc: " << it->ssrcs[0];
} else {
LOG(LS_INFO) << "Failed to add send stream ssrc: " << it->first_ssrc();
std::ostringstream desc;
desc << "Failed to add send stream ssrc: " << it->first_ssrc();
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
@ -1266,7 +1302,8 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
bool BaseChannel::UpdateRemoteStreams_w(
const std::vector<StreamParams>& streams,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
action == CA_PRANSWER || action == CA_UPDATE))
return false;
@ -1283,15 +1320,18 @@ bool BaseChannel::UpdateRemoteStreams_w(
remote_streams_.push_back(*it);
LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
} else {
LOG(LS_INFO) << "Failed to add remote stream ssrc: "
<< it->first_ssrc();
std::ostringstream desc;
desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
SafeSetError(desc.str(), error_desc);
return false;
}
} else if (stream_exists && !it->has_ssrcs()) {
if (!RemoveRecvStream_w(existing_stream.first_ssrc())) {
LOG(LS_ERROR) << "Failed to remove remote stream with ssrc "
<< it->first_ssrc() << ".";
return false;
std::ostringstream desc;
desc << "Failed to remove remote stream with ssrc "
<< it->first_ssrc() << ".";
SafeSetError(desc.str(), error_desc);
return false;
}
RemoveStreamBySsrc(&remote_streams_, existing_stream.first_ssrc());
} else {
@ -1311,8 +1351,10 @@ bool BaseChannel::UpdateRemoteStreams_w(
it != remote_streams_.end(); ++it) {
if (!GetStreamBySsrc(streams, it->first_ssrc(), NULL)) {
if (!RemoveRecvStream_w(it->first_ssrc())) {
LOG(LS_ERROR) << "Failed to remove remote stream with ssrc "
<< it->first_ssrc() << ".";
std::ostringstream desc;
desc << "Failed to remove remote stream with ssrc "
<< it->first_ssrc() << ".";
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
@ -1324,8 +1366,9 @@ bool BaseChannel::UpdateRemoteStreams_w(
if (AddRecvStream_w(*it)) {
LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
} else {
LOG(LS_INFO) << "Failed to add remote stream ssrc: "
<< it->first_ssrc();
std::ostringstream desc;
desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
@ -1335,37 +1378,56 @@ bool BaseChannel::UpdateRemoteStreams_w(
}
bool BaseChannel::SetBaseLocalContent_w(const MediaContentDescription* content,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
// Cache secure_required_ for belt and suspenders check on SendPacket
secure_required_ = content->crypto_required();
bool ret = UpdateLocalStreams_w(content->streams(), action);
bool ret = UpdateLocalStreams_w(content->streams(), action, error_desc);
// Set local SRTP parameters (what we will encrypt with).
ret &= SetSrtp_w(content->cryptos(), action, CS_LOCAL);
ret &= SetSrtp_w(content->cryptos(), action, CS_LOCAL, error_desc);
// Set local RTCP mux parameters.
ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_LOCAL);
ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_LOCAL, error_desc);
// Set local RTP header extensions.
if (content->rtp_header_extensions_set()) {
ret &= media_channel()->SetRecvRtpHeaderExtensions(
content->rtp_header_extensions());
if (!media_channel()->SetRecvRtpHeaderExtensions(
content->rtp_header_extensions())) {
std::ostringstream desc;
desc << "Failed to set receive rtp header extensions for "
<< MediaTypeToString(content->type()) << " content.";
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
set_local_content_direction(content->direction());
return ret;
}
bool BaseChannel::SetBaseRemoteContent_w(const MediaContentDescription* content,
ContentAction action) {
bool ret = UpdateRemoteStreams_w(content->streams(), action);
ContentAction action,
std::string* error_desc) {
bool ret = UpdateRemoteStreams_w(content->streams(), action, error_desc);
// Set remote SRTP parameters (what the other side will encrypt with).
ret &= SetSrtp_w(content->cryptos(), action, CS_REMOTE);
ret &= SetSrtp_w(content->cryptos(), action, CS_REMOTE, error_desc);
// Set remote RTCP mux parameters.
ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_REMOTE);
ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_REMOTE, error_desc);
// Set remote RTP header extensions.
if (content->rtp_header_extensions_set()) {
ret &= media_channel()->SetSendRtpHeaderExtensions(
content->rtp_header_extensions());
if (!media_channel()->SetSendRtpHeaderExtensions(
content->rtp_header_extensions())) {
std::ostringstream desc;
desc << "Failed to set send rtp header extensions for "
<< MediaTypeToString(content->type()) << " content.";
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
if (content->bandwidth() != kAutoBandwidth) {
ret &= media_channel()->SetSendBandwidth(false, content->bandwidth());
if (!media_channel()->SetMaxSendBandwidth(content->bandwidth())) {
std::ostringstream desc;
desc << "Failed to set max send bandwidth for "
<< MediaTypeToString(content->type()) << " content.";
SafeSetError(desc.str(), error_desc);
ret = false;
}
set_remote_content_direction(content->direction());
return ret;
@ -1391,12 +1453,16 @@ void BaseChannel::OnMessage(talk_base::Message *pmsg) {
}
case MSG_SETLOCALCONTENT: {
SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
data->result = SetLocalContent_w(data->content, data->action);
data->result = SetLocalContent_w(data->content,
data->action,
data->error_desc);
break;
}
case MSG_SETREMOTECONTENT: {
SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
data->result = SetRemoteContent_w(data->content, data->action);
data->result = SetRemoteContent_w(data->content,
data->action,
data->error_desc);
break;
}
case MSG_ADDRECVSTREAM: {
@ -1419,11 +1485,6 @@ void BaseChannel::OnMessage(talk_base::Message *pmsg) {
data->result = RemoveSendStream_w(data->ssrc);
break;
}
case MSG_SETMAXSENDBANDWIDTH: {
SetBandwidthData* data = static_cast<SetBandwidthData*>(pmsg->pdata);
data->result = SetMaxSendBandwidth_w(data->value);
break;
}
case MSG_RTPPACKET:
case MSG_RTCPPACKET: {
@ -1439,7 +1500,7 @@ void BaseChannel::OnMessage(talk_base::Message *pmsg) {
case MSG_SESSION_ERROR: {
SessionErrorMessageData* data = static_cast<SessionErrorMessageData*>
(pmsg->pdata);
session_->SetError(data->error_);
SetSessionError(session_, data->error_, data->error_desc_);
break;
}
}
@ -1685,21 +1746,28 @@ const ContentInfo* VoiceChannel::GetFirstContent(
}
bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting local voice description";
const AudioContentDescription* audio =
static_cast<const AudioContentDescription*>(content);
ASSERT(audio != NULL);
if (!audio) return false;
if (!audio) {
SafeSetError("Can't find audio content in local description.", error_desc);
return false;
}
bool ret = SetBaseLocalContent_w(content, action);
bool ret = SetBaseLocalContent_w(content, action, error_desc);
// Set local audio codecs (what we want to receive).
// TODO(whyuan): Change action != CA_UPDATE to !audio->partial() when partial
// is set properly.
if (action != CA_UPDATE || audio->has_codecs()) {
ret &= media_channel()->SetRecvCodecs(audio->codecs());
if (!media_channel()->SetRecvCodecs(audio->codecs())) {
SafeSetError("Failed to set audio receive codecs.", error_desc);
ret = false;
}
}
// If everything worked, see if we can start receiving.
@ -1712,22 +1780,29 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
}
bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting remote voice description";
const AudioContentDescription* audio =
static_cast<const AudioContentDescription*>(content);
ASSERT(audio != NULL);
if (!audio) return false;
if (!audio) {
SafeSetError("Can't find audio content in remote description.", error_desc);
return false;
}
bool ret = true;
// Set remote video codecs (what the other side wants to receive).
if (action != CA_UPDATE || audio->has_codecs()) {
ret &= media_channel()->SetSendCodecs(audio->codecs());
if (!media_channel()->SetSendCodecs(audio->codecs())) {
SafeSetError("Failed to set audio send codecs.", error_desc);
ret = false;
}
}
ret &= SetBaseRemoteContent_w(content, action);
ret &= SetBaseRemoteContent_w(content, action, error_desc);
if (action != CA_UPDATE) {
// Tweak our audio processing settings, if needed.
@ -2104,19 +2179,26 @@ const ContentInfo* VideoChannel::GetFirstContent(
}
bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting local video description";
const VideoContentDescription* video =
static_cast<const VideoContentDescription*>(content);
ASSERT(video != NULL);
if (!video) return false;
if (!video) {
SafeSetError("Can't find video content in local description.", error_desc);
return false;
}
bool ret = SetBaseLocalContent_w(content, action);
bool ret = SetBaseLocalContent_w(content, action, error_desc);
// Set local video codecs (what we want to receive).
if (action != CA_UPDATE || video->has_codecs()) {
ret &= media_channel()->SetRecvCodecs(video->codecs());
if (!media_channel()->SetRecvCodecs(video->codecs())) {
SafeSetError("Failed to set video receive codecs.", error_desc);
ret = false;
}
}
if (action != CA_UPDATE) {
@ -2140,22 +2222,29 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
}
bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting remote video description";
const VideoContentDescription* video =
static_cast<const VideoContentDescription*>(content);
ASSERT(video != NULL);
if (!video) return false;
if (!video) {
SafeSetError("Can't find video content in remote description.", error_desc);
return false;
}
bool ret = true;
// Set remote video codecs (what the other side wants to receive).
if (action != CA_UPDATE || video->has_codecs()) {
ret &= media_channel()->SetSendCodecs(video->codecs());
if (!media_channel()->SetSendCodecs(video->codecs())) {
SafeSetError("Failed to set video send codecs.", error_desc);
ret = false;
}
}
ret &= SetBaseRemoteContent_w(content, action);
ret &= SetBaseRemoteContent_w(content, action, error_desc);
if (action != CA_UPDATE) {
// Tweak our video processing settings, if needed.
@ -2553,13 +2642,8 @@ bool DataChannel::WantsPacket(bool rtcp, talk_base::Buffer* packet) {
return false;
}
// Sets the maximum bandwidth. Anything over this will be dropped.
bool DataChannel::SetMaxSendBandwidth_w(int max_bps) {
LOG(LS_INFO) << "DataChannel: Setting max bandwidth to " << max_bps;
return media_channel()->SetSendBandwidth(false, max_bps);
}
bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type) {
bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
std::string* error_desc) {
// It hasn't been set before, so set it now.
if (data_channel_type_ == DCT_NONE) {
data_channel_type_ = new_data_channel_type;
@ -2568,9 +2652,11 @@ bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type) {
// It's been set before, but doesn't match. That's bad.
if (data_channel_type_ != new_data_channel_type) {
LOG(LS_WARNING) << "Data channel type mismatch."
<< " Expected " << data_channel_type_
<< " Got " << new_data_channel_type;
std::ostringstream desc;
desc << "Data channel type mismatch."
<< " Expected " << data_channel_type_
<< " Got " << new_data_channel_type;
SafeSetError(desc.str(), error_desc);
return false;
}
@ -2579,42 +2665,53 @@ bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type) {
}
bool DataChannel::SetDataChannelTypeFromContent(
const DataContentDescription* content) {
const DataContentDescription* content,
std::string* error_desc) {
bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
(content->protocol() == kMediaProtocolDtlsSctp));
DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
return SetDataChannelType(data_channel_type);
return SetDataChannelType(data_channel_type, error_desc);
}
bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current());
LOG(LS_INFO) << "Setting local data description";
const DataContentDescription* data =
static_cast<const DataContentDescription*>(content);
ASSERT(data != NULL);
if (!data) return false;
if (!data) {
SafeSetError("Can't find data content in local description.", error_desc);
return false;
}
bool ret = false;
if (!SetDataChannelTypeFromContent(data)) {
if (!SetDataChannelTypeFromContent(data, error_desc)) {
return false;
}
if (data_channel_type_ == DCT_SCTP) {
// SCTP data channels don't need the rest of the stuff.
ret = UpdateLocalStreams_w(data->streams(), action);
ret = UpdateLocalStreams_w(data->streams(), action, error_desc);
if (ret) {
set_local_content_direction(content->direction());
// As in SetRemoteContent_w, make sure we set the local SCTP port
// number as specified in our DataContentDescription.
ret = media_channel()->SetRecvCodecs(data->codecs());
if (!media_channel()->SetRecvCodecs(data->codecs())) {
SafeSetError("Failed to set data receive codecs.", error_desc);
ret = false;
}
}
} else {
ret = SetBaseLocalContent_w(content, action);
ret = SetBaseLocalContent_w(content, action, error_desc);
if (action != CA_UPDATE || data->has_codecs()) {
ret &= media_channel()->SetRecvCodecs(data->codecs());
if (!media_channel()->SetRecvCodecs(data->codecs())) {
SafeSetError("Failed to set data receive codecs.", error_desc);
ret = false;
}
}
}
@ -2628,28 +2725,35 @@ bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
}
bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) {
ContentAction action,
std::string* error_desc) {
ASSERT(worker_thread() == talk_base::Thread::Current());
const DataContentDescription* data =
static_cast<const DataContentDescription*>(content);
ASSERT(data != NULL);
if (!data) return false;
if (!data) {
SafeSetError("Can't find data content in remote description.", error_desc);
return false;
}
bool ret = true;
if (!SetDataChannelTypeFromContent(data)) {
if (!SetDataChannelTypeFromContent(data, error_desc)) {
return false;
}
if (data_channel_type_ == DCT_SCTP) {
LOG(LS_INFO) << "Setting SCTP remote data description";
// SCTP data channels don't need the rest of the stuff.
ret = UpdateRemoteStreams_w(content->streams(), action);
ret = UpdateRemoteStreams_w(content->streams(), action, error_desc);
if (ret) {
set_remote_content_direction(content->direction());
// We send the SCTP port number (not to be confused with the underlying
// UDP port number) as a codec parameter. Make sure it gets there.
ret = media_channel()->SetSendCodecs(data->codecs());
if (!media_channel()->SetSendCodecs(data->codecs())) {
SafeSetError("Failed to set data send codecs.", error_desc);
ret = false;
}
}
} else {
// If the remote data doesn't have codecs and isn't an update, it
@ -2661,17 +2765,24 @@ bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
// Set remote video codecs (what the other side wants to receive).
if (action != CA_UPDATE || data->has_codecs()) {
ret &= media_channel()->SetSendCodecs(data->codecs());
if (!media_channel()->SetSendCodecs(data->codecs())) {
SafeSetError("Failed to set data send codecs.", error_desc);
ret = false;
}
}
if (ret) {
ret &= SetBaseRemoteContent_w(content, action);
ret &= SetBaseRemoteContent_w(content, action, error_desc);
}
if (action != CA_UPDATE) {
int bandwidth_bps = data->bandwidth();
bool auto_bandwidth = (bandwidth_bps == kAutoBandwidth);
ret &= media_channel()->SetSendBandwidth(auto_bandwidth, bandwidth_bps);
if (!media_channel()->SetMaxSendBandwidth(bandwidth_bps)) {
std::ostringstream desc;
desc << "Failed to set max send bandwidth for data content.";
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
}

View File

@ -111,10 +111,11 @@ class BaseChannel
// Channel control
bool SetLocalContent(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
bool SetRemoteContent(const MediaContentDescription* content,
ContentAction action);
bool SetMaxSendBandwidth(int max_bandwidth);
ContentAction action,
std::string* error_desc);
bool Enable(bool enable);
// Mute sending media on the stream with SSRC |ssrc|
@ -306,24 +307,35 @@ class BaseChannel
virtual const ContentInfo* GetFirstContent(
const SessionDescription* sdesc) = 0;
bool UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
ContentAction action);
ContentAction action,
std::string* error_desc);
bool UpdateRemoteStreams_w(const std::vector<StreamParams>& streams,
ContentAction action);
ContentAction action,
std::string* error_desc);
bool SetBaseLocalContent_w(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
virtual bool SetLocalContent_w(const MediaContentDescription* content,
ContentAction action) = 0;
ContentAction action,
std::string* error_desc) = 0;
bool SetBaseRemoteContent_w(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) = 0;
ContentAction action,
std::string* error_desc) = 0;
bool CheckSrtpConfig(const std::vector<CryptoParams>& cryptos, bool* dtls);
bool SetSrtp_w(const std::vector<CryptoParams>& params, ContentAction action,
ContentSource src);
bool SetRtcpMux_w(bool enable, ContentAction action, ContentSource src);
virtual bool SetMaxSendBandwidth_w(int max_bandwidth);
bool CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
bool* dtls,
std::string* error_desc);
bool SetSrtp_w(const std::vector<CryptoParams>& params,
ContentAction action,
ContentSource src,
std::string* error_desc);
bool SetRtcpMux_w(bool enable,
ContentAction action,
ContentSource src,
std::string* error_desc);
// From MessageHandler
virtual void OnMessage(talk_base::Message* pmsg);
@ -450,9 +462,11 @@ class VoiceChannel : public BaseChannel {
virtual void ChangeState();
virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc);
virtual bool SetLocalContent_w(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
bool SetRingbackTone_w(const void* buf, int len);
bool PlayRingbackTone_w(uint32 ssrc, bool play, bool loop);
void HandleEarlyMediaTimeout();
@ -549,9 +563,11 @@ class VideoChannel : public BaseChannel {
virtual void ChangeState();
virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc);
virtual bool SetLocalContent_w(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
void SendIntraFrame_w() {
media_channel()->SendIntraFrame();
}
@ -677,15 +693,18 @@ class DataChannel : public BaseChannel {
// If data_channel_type_ is DCT_NONE, set it. Otherwise, check that
// it's the same as what was set previously. Returns false if it's
// set to one type one type and changed to another type later.
bool SetDataChannelType(DataChannelType new_data_channel_type);
bool SetDataChannelType(DataChannelType new_data_channel_type,
std::string* error_desc);
// Same as SetDataChannelType, but extracts the type from the
// DataContentDescription.
bool SetDataChannelTypeFromContent(const DataContentDescription* content);
virtual bool SetMaxSendBandwidth_w(int max_bandwidth);
bool SetDataChannelTypeFromContent(const DataContentDescription* content,
std::string* error_desc);
virtual bool SetLocalContent_w(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action);
ContentAction action,
std::string* error_desc);
virtual void ChangeState();
virtual bool WantsPacket(bool rtcp, talk_base::Buffer* packet);

View File

@ -318,14 +318,17 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
}
bool SendInitiate() {
bool result = channel1_->SetLocalContent(&local_media_content1_, CA_OFFER);
bool result = channel1_->SetLocalContent(&local_media_content1_,
CA_OFFER, NULL);
if (result) {
channel1_->Enable(true);
result = channel2_->SetRemoteContent(&remote_media_content1_, CA_OFFER);
result = channel2_->SetRemoteContent(&remote_media_content1_,
CA_OFFER, NULL);
if (result) {
session1_.Connect(&session2_);
result = channel2_->SetLocalContent(&local_media_content2_, CA_ANSWER);
result = channel2_->SetLocalContent(&local_media_content2_,
CA_ANSWER, NULL);
}
}
return result;
@ -333,34 +336,39 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
bool SendAccept() {
channel2_->Enable(true);
return channel1_->SetRemoteContent(&remote_media_content2_, CA_ANSWER);
return channel1_->SetRemoteContent(&remote_media_content2_,
CA_ANSWER, NULL);
}
bool SendOffer() {
bool result = channel1_->SetLocalContent(&local_media_content1_, CA_OFFER);
bool result = channel1_->SetLocalContent(&local_media_content1_,
CA_OFFER, NULL);
if (result) {
channel1_->Enable(true);
result = channel2_->SetRemoteContent(&remote_media_content1_, CA_OFFER);
result = channel2_->SetRemoteContent(&remote_media_content1_,
CA_OFFER, NULL);
}
return result;
}
bool SendProvisionalAnswer() {
bool result = channel2_->SetLocalContent(&local_media_content2_,
CA_PRANSWER);
CA_PRANSWER, NULL);
if (result) {
channel2_->Enable(true);
result = channel1_->SetRemoteContent(&remote_media_content2_,
CA_PRANSWER);
CA_PRANSWER, NULL);
session1_.Connect(&session2_);
}
return result;
}
bool SendFinalAnswer() {
bool result = channel2_->SetLocalContent(&local_media_content2_, CA_ANSWER);
bool result = channel2_->SetLocalContent(&local_media_content2_,
CA_ANSWER, NULL);
if (result)
result = channel1_->SetRemoteContent(&remote_media_content2_, CA_ANSWER);
result = channel1_->SetRemoteContent(&remote_media_content2_,
CA_ANSWER, NULL);
return result;
}
@ -591,9 +599,9 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateChannels(0, 0);
typename T::Content content;
CreateContent(0, kPcmuCodec, kH264Codec, &content);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_EQ(0U, media_channel1_->codecs().size());
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(content.codecs()[0],
media_channel1_->codecs()[0]));
@ -604,10 +612,10 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
void TestSetContentsNullOffer() {
CreateChannels(0, 0);
typename T::Content content;
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
CreateContent(0, kPcmuCodec, kH264Codec, &content);
EXPECT_EQ(0U, media_channel1_->codecs().size());
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(content.codecs()[0],
media_channel1_->codecs()[0]));
@ -623,13 +631,13 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateContent(0, kPcmuCodec, kH264Codec, &content);
// Both sides agree on mux. Should no longer be a separate RTCP channel.
content.set_rtcp_mux(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
// Only initiator supports mux. Should still have a separate RTCP channel.
EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER, NULL));
content.set_rtcp_mux(false);
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER, NULL));
EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL);
}
@ -642,17 +650,17 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content;
CreateContent(0, kPcmuCodec, kH264Codec, &content);
content.set_rtcp_mux(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_PRANSWER));
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_PRANSWER, NULL));
EXPECT_TRUE(channel1_->rtcp_transport_channel() != NULL);
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
// Both sides agree on mux. Should no longer be a separate RTCP channel.
EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
// Only initiator supports mux. Should still have a separate RTCP channel.
EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER, NULL));
content.set_rtcp_mux(false);
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_PRANSWER));
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_PRANSWER, NULL));
EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER, NULL));
EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL);
}
@ -663,7 +671,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content;
CreateContent(0, kPcmuCodec, kH264Codec, &content);
content.set_buffered_mode_latency(101);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_EQ(0U, media_channel1_->codecs().size());
cricket::VideoOptions options;
ASSERT_TRUE(media_channel1_->GetOptions(&options));
@ -671,7 +679,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(options.buffered_mode_latency.Get(&latency));
EXPECT_EQ(101, latency);
content.set_buffered_mode_latency(102);
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(content.codecs()[0],
media_channel1_->codecs()[0]));
@ -688,8 +696,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
kPcmuCodec, kH264Codec,
&content);
EXPECT_EQ(0U, media_channel1_->codecs().size());
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(content.codecs()[0],
media_channel1_->codecs()[0]));
@ -698,14 +706,14 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
update_content.set_partial(true);
CreateContent(0, kIsacCodec, kH264SvcCodec,
&update_content);
EXPECT_TRUE(channel1_->SetRemoteContent(&update_content, CA_UPDATE));
EXPECT_TRUE(channel1_->SetRemoteContent(&update_content, CA_UPDATE, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(update_content.codecs()[0],
media_channel1_->codecs()[0]));
// Now update without any codecs. This is ignored.
typename T::Content empty_content;
empty_content.set_partial(true);
EXPECT_TRUE(channel1_->SetRemoteContent(&empty_content, CA_UPDATE));
EXPECT_TRUE(channel1_->SetRemoteContent(&empty_content, CA_UPDATE, NULL));
ASSERT_EQ(1U, media_channel1_->codecs().size());
EXPECT_TRUE(CodecMatches(update_content.codecs()[0],
media_channel1_->codecs()[0]));
@ -751,7 +759,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateContent(0, kPcmuCodec, kH264Codec, &content1);
content1.AddStream(stream1);
EXPECT_EQ(0u, media_channel1_->send_streams().size());
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER));
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER, NULL));
ASSERT_EQ(1u, media_channel1_->send_streams().size());
EXPECT_EQ(stream1, media_channel1_->send_streams()[0]);
@ -762,7 +770,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
content2.AddStream(stream2);
content2.AddStream(stream3);
content2.set_partial(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content2, CA_UPDATE));
EXPECT_TRUE(channel1_->SetLocalContent(&content2, CA_UPDATE, NULL));
ASSERT_EQ(3u, media_channel1_->send_streams().size());
EXPECT_EQ(stream1, media_channel1_->send_streams()[0]);
EXPECT_EQ(stream2, media_channel1_->send_streams()[1]);
@ -774,7 +782,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
stream1.ssrcs.clear();
content3.AddStream(stream1);
content3.set_partial(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content3, CA_UPDATE));
EXPECT_TRUE(channel1_->SetLocalContent(&content3, CA_UPDATE, NULL));
ASSERT_EQ(2u, media_channel1_->send_streams().size());
EXPECT_EQ(stream2, media_channel1_->send_streams()[0]);
EXPECT_EQ(stream3, media_channel1_->send_streams()[1]);
@ -784,7 +792,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content4;
content4.AddStream(stream2);
content4.set_partial(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content4, CA_UPDATE));
EXPECT_TRUE(channel1_->SetLocalContent(&content4, CA_UPDATE, NULL));
ASSERT_EQ(2u, media_channel1_->send_streams().size());
EXPECT_EQ(stream2, media_channel1_->send_streams()[0]);
EXPECT_EQ(stream3, media_channel1_->send_streams()[1]);
@ -818,7 +826,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateContent(0, kPcmuCodec, kH264Codec, &content1);
content1.AddStream(stream1);
EXPECT_EQ(0u, media_channel1_->recv_streams().size());
EXPECT_TRUE(channel1_->SetRemoteContent(&content1, CA_OFFER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content1, CA_OFFER, NULL));
ASSERT_EQ(1u, media_channel1_->codecs().size());
ASSERT_EQ(1u, media_channel1_->recv_streams().size());
@ -830,7 +838,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
content2.AddStream(stream2);
content2.AddStream(stream3);
content2.set_partial(true);
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_UPDATE));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_UPDATE, NULL));
ASSERT_EQ(3u, media_channel1_->recv_streams().size());
EXPECT_EQ(stream1, media_channel1_->recv_streams()[0]);
EXPECT_EQ(stream2, media_channel1_->recv_streams()[1]);
@ -842,7 +850,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
stream1.ssrcs.clear();
content3.AddStream(stream1);
content3.set_partial(true);
EXPECT_TRUE(channel1_->SetRemoteContent(&content3, CA_UPDATE));
EXPECT_TRUE(channel1_->SetRemoteContent(&content3, CA_UPDATE, NULL));
ASSERT_EQ(2u, media_channel1_->recv_streams().size());
EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]);
EXPECT_EQ(stream3, media_channel1_->recv_streams()[1]);
@ -852,7 +860,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content4;
content4.AddStream(stream2);
content4.set_partial(true);
EXPECT_TRUE(channel1_->SetRemoteContent(&content4, CA_UPDATE));
EXPECT_TRUE(channel1_->SetRemoteContent(&content4, CA_UPDATE, NULL));
ASSERT_EQ(2u, media_channel1_->recv_streams().size());
EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]);
EXPECT_EQ(stream3, media_channel1_->recv_streams()[1]);
@ -879,20 +887,20 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content1;
CreateContent(0, kPcmuCodec, kH264Codec, &content1);
content1.AddStream(stream1);
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER));
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->Enable(true));
EXPECT_EQ(1u, media_channel1_->send_streams().size());
EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER));
EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER, NULL));
EXPECT_EQ(1u, media_channel2_->recv_streams().size());
session1_.Connect(&session2_);
// Channel 2 do not send anything.
typename T::Content content2;
CreateContent(0, kPcmuCodec, kH264Codec, &content2);
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_ANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_ANSWER, NULL));
EXPECT_EQ(0u, media_channel1_->recv_streams().size());
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_ANSWER));
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_ANSWER, NULL));
EXPECT_TRUE(channel2_->Enable(true));
EXPECT_EQ(0u, media_channel2_->send_streams().size());
@ -903,21 +911,21 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
typename T::Content content3;
CreateContent(SECURE, kPcmuCodec, kH264Codec, &content3);
content3.AddStream(stream2);
EXPECT_TRUE(channel2_->SetLocalContent(&content3, CA_OFFER));
EXPECT_TRUE(channel2_->SetLocalContent(&content3, CA_OFFER, NULL));
ASSERT_EQ(1u, media_channel2_->send_streams().size());
EXPECT_EQ(stream2, media_channel2_->send_streams()[0]);
EXPECT_TRUE(channel1_->SetRemoteContent(&content3, CA_OFFER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content3, CA_OFFER, NULL));
ASSERT_EQ(1u, media_channel1_->recv_streams().size());
EXPECT_EQ(stream2, media_channel1_->recv_streams()[0]);
// Channel 1 replies but stop sending stream1.
typename T::Content content4;
CreateContent(SECURE, kPcmuCodec, kH264Codec, &content4);
EXPECT_TRUE(channel1_->SetLocalContent(&content4, CA_ANSWER));
EXPECT_TRUE(channel1_->SetLocalContent(&content4, CA_ANSWER, NULL));
EXPECT_EQ(0u, media_channel1_->send_streams().size());
EXPECT_TRUE(channel2_->SetRemoteContent(&content4, CA_ANSWER));
EXPECT_TRUE(channel2_->SetRemoteContent(&content4, CA_ANSWER, NULL));
EXPECT_EQ(0u, media_channel2_->recv_streams().size());
EXPECT_TRUE(channel1_->secure());
@ -936,13 +944,16 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(channel1_->Enable(true));
EXPECT_FALSE(media_channel1_->playout());
EXPECT_FALSE(media_channel1_->sending());
EXPECT_TRUE(channel1_->SetLocalContent(&local_media_content1_, CA_OFFER));
EXPECT_TRUE(channel1_->SetLocalContent(&local_media_content1_,
CA_OFFER, NULL));
EXPECT_TRUE(media_channel1_->playout());
EXPECT_FALSE(media_channel1_->sending());
EXPECT_TRUE(channel2_->SetRemoteContent(&local_media_content1_, CA_OFFER));
EXPECT_TRUE(channel2_->SetRemoteContent(&local_media_content1_,
CA_OFFER, NULL));
EXPECT_FALSE(media_channel2_->playout());
EXPECT_FALSE(media_channel2_->sending());
EXPECT_TRUE(channel2_->SetLocalContent(&local_media_content2_, CA_ANSWER));
EXPECT_TRUE(channel2_->SetLocalContent(&local_media_content2_,
CA_ANSWER, NULL));
EXPECT_FALSE(media_channel2_->playout());
EXPECT_FALSE(media_channel2_->sending());
session1_.Connect(&session2_);
@ -953,7 +964,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(channel2_->Enable(true));
EXPECT_TRUE(media_channel2_->playout());
EXPECT_TRUE(media_channel2_->sending());
EXPECT_TRUE(channel1_->SetRemoteContent(&local_media_content2_, CA_ANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&local_media_content2_,
CA_ANSWER, NULL));
EXPECT_TRUE(media_channel1_->playout());
EXPECT_TRUE(media_channel1_->sending());
}
@ -998,10 +1010,10 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_FALSE(media_channel2_->playout());
EXPECT_FALSE(media_channel2_->sending());
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER));
EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER));
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER));
EXPECT_TRUE(channel1_->SetLocalContent(&content1, CA_OFFER, NULL));
EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER, NULL));
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER, NULL));
session1_.Connect(&session2_);
EXPECT_TRUE(media_channel1_->playout());
@ -1011,8 +1023,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
// Update |content2| to be RecvOnly.
content2.set_direction(cricket::MD_RECVONLY);
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER));
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER, NULL));
EXPECT_TRUE(media_channel1_->playout());
EXPECT_TRUE(media_channel1_->sending());
@ -1021,8 +1033,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
// Update |content2| to be SendRecv.
content2.set_direction(cricket::MD_SENDRECV);
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_ANSWER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_ANSWER));
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_ANSWER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_ANSWER, NULL));
EXPECT_TRUE(media_channel1_->playout());
EXPECT_TRUE(media_channel1_->sending());
@ -1587,21 +1599,21 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
// Test failures in SetLocalContent.
media_channel1_->set_fail_set_recv_codecs(true);
session1_.SetError(cricket::BaseSession::ERROR_NONE);
session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_SENTINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
media_channel1_->set_fail_set_recv_codecs(true);
session1_.SetError(cricket::BaseSession::ERROR_NONE);
session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_SENTACCEPT);
EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
// Test failures in SetRemoteContent.
media_channel1_->set_fail_set_send_codecs(true);
session1_.SetError(cricket::BaseSession::ERROR_NONE);
session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
media_channel1_->set_fail_set_send_codecs(true);
session1_.SetError(cricket::BaseSession::ERROR_NONE);
session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_RECEIVEDACCEPT);
EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
}
@ -1613,7 +1625,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1);
EXPECT_TRUE(session1_.set_local_description(sdesc));
session1_.SetError(cricket::BaseSession::ERROR_NONE);
session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_SENTINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
EXPECT_TRUE(media_channel1_->HasSendStream(1));
@ -1635,7 +1647,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1);
EXPECT_TRUE(session1_.set_remote_description(sdesc));
session1_.SetError(cricket::BaseSession::ERROR_NONE);
session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
EXPECT_TRUE(media_channel1_->HasRecvStream(1));
@ -1655,7 +1667,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1);
EXPECT_TRUE(session1_.set_remote_description(sdesc));
session1_.SetError(cricket::BaseSession::ERROR_NONE);
session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
EXPECT_TRUE(media_channel1_->HasRecvStream(1));
@ -1687,7 +1699,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
cricket::SessionDescription* sdesc = CreateSessionDescriptionWithStream(1);
EXPECT_TRUE(session1_.set_local_description(sdesc));
session1_.SetError(cricket::BaseSession::ERROR_NONE);
session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
session1_.SetState(cricket::Session::STATE_SENTINITIATE);
EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
EXPECT_TRUE(media_channel1_->HasSendStream(1));
@ -1810,8 +1822,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
CreateContent(0, kPcmuCodec, kH264Codec, &content);
// Both sides agree on mux. Should no longer be a separate RTCP channel.
content.set_rtcp_mux(true);
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER));
EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
TransportChannel* rtp = channel1_->transport_channel();
EXPECT_FALSE(media_channel1_->ready_to_send());

View File

@ -1024,6 +1024,25 @@ static bool IsDtlsActive(
return current_tdesc->secure();
}
std::string MediaTypeToString(MediaType type) {
std::string type_str;
switch (type) {
case MEDIA_TYPE_AUDIO:
type_str = "audio";
break;
case MEDIA_TYPE_VIDEO:
type_str = "video";
break;
case MEDIA_TYPE_DATA:
type_str = "data";
break;
default:
ASSERT(false);
break;
}
return type_str;
}
void MediaSessionOptions::AddStream(MediaType type,
const std::string& id,
const std::string& sync_label) {

View File

@ -63,6 +63,8 @@ enum MediaType {
MEDIA_TYPE_DATA
};
std::string MediaTypeToString(MediaType type);
enum MediaContentDirection {
MD_INACTIVE,
MD_SENDONLY,