Update libjingle to 53856368.

R=mallinath@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4941 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
wu@webrtc.org
2013-10-07 23:32:02 +00:00
parent e0d55a0782
commit 7818752566
42 changed files with 694 additions and 202 deletions

View File

@@ -85,6 +85,7 @@ const char* kRtcpFbCcmParamFir = "fir";
const char* kCodecParamMaxBitrate = "x-google-max-bitrate";
const char* kCodecParamMinBitrate = "x-google-min-bitrate";
const char* kCodecParamMaxQuantization = "x-google-max-quantization";
const char* kCodecParamPort = "x-google-port";
const int kGoogleRtpDataCodecId = 101;
const char kGoogleRtpDataCodecName[] = "google-data";

View File

@@ -99,6 +99,7 @@ extern const char* kRtcpFbCcmParamFir;
extern const char* kCodecParamMaxBitrate;
extern const char* kCodecParamMinBitrate;
extern const char* kCodecParamMaxQuantization;
extern const char* kCodecParamPort;
// We put the data codec names here so callers of
// DataEngine::CreateChannel don't have to import rtpdataengine.h or

View File

@@ -837,6 +837,9 @@ class FakeVideoEngine : public FakeBaseEngine {
default_encoder_config_ = config;
return true;
}
VideoEncoderConfig GetDefaultEncoderConfig() const {
return default_encoder_config_;
}
const VideoEncoderConfig& default_encoder_config() const {
return default_encoder_config_;
}

View File

@@ -93,6 +93,9 @@ class FileMediaEngine : public MediaEngineInterface {
virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) {
return true;
}
virtual VideoEncoderConfig GetDefaultVideoEncoderConfig() const {
return VideoEncoderConfig();
}
virtual bool SetSoundDevices(const Device* in_dev, const Device* out_dev) {
return true;
}

View File

@@ -204,6 +204,20 @@ class HybridVideoEngine : public HybridVideoEngineInterface {
}
return true;
}
VideoEncoderConfig GetDefaultEncoderConfig() const {
// This looks pretty strange, but, in practice, it'll do sane things if
// GetDefaultEncoderConfig is only called after SetDefaultEncoderConfig,
// since both engines should be essentially equivalent at that point. If it
// hasn't been called, though, we'll use the first meaningful encoder
// config, or the config from the second video engine if neither are
// meaningful.
VideoEncoderConfig config = video1_.GetDefaultEncoderConfig();
if (config.max_codec.width != 0) {
return config;
} else {
return video2_.GetDefaultEncoderConfig();
}
}
const std::vector<VideoCodec>& codecs() const {
return codecs_;
}

View File

@@ -98,6 +98,10 @@ class MediaEngineInterface {
// and encode video.
virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config)
= 0;
// Gets the default (maximum) codec/resolution and encoder option used to
// capture and encode video, as set by SetDefaultVideoEncoderConfig or the
// default from the video engine if not previously set.
virtual VideoEncoderConfig GetDefaultVideoEncoderConfig() const = 0;
// Device selection
// TODO(tschmelcher): Add method for selecting the soundclip device.
@@ -203,6 +207,9 @@ class CompositeMediaEngine : public MediaEngineInterface {
virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) {
return video_.SetDefaultEncoderConfig(config);
}
virtual VideoEncoderConfig GetDefaultVideoEncoderConfig() const {
return video_.GetDefaultEncoderConfig();
}
virtual bool SetSoundDevices(const Device* in_device,
const Device* out_device) {
@@ -327,6 +334,9 @@ class NullVideoEngine {
return NULL;
}
bool SetOptions(const VideoOptions& options) { return true; }
VideoEncoderConfig GetDefaultEncoderConfig() const {
return VideoEncoderConfig();
}
bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) {
return true;
}

View File

@@ -27,6 +27,10 @@
#include "talk/media/devices/libudevsymboltable.h"
#include <dlfcn.h>
#include "talk/base/logging.h"
namespace cricket {
#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBUDEV_SYMBOLS_CLASS_NAME
@@ -37,4 +41,30 @@ namespace cricket {
#undef LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST
#undef LATE_BINDING_SYMBOL_TABLE_DLL_NAME
bool IsWrongLibUDevAbiVersion(talk_base::DllHandle libudev_0) {
talk_base::DllHandle libudev_1 = dlopen("libudev.so.1", RTLD_NOW|RTLD_NOLOAD);
bool unsafe_symlink = (libudev_0 == libudev_1);
if (unsafe_symlink) {
// .0 and .1 are distinct ABIs, so if they point to the same thing then one
// of them must be wrong. Probably the old has been symlinked to the new in
// a misguided attempt at backwards compatibility.
LOG(LS_ERROR) << "libudev.so.0 and libudev.so.1 unsafely point to the"
" same thing; not using libudev";
} else if (libudev_1) {
// If libudev.so.1 is resident but distinct from libudev.so.0, then some
// system library loaded the new ABI separately. This is not a problem for
// LateBindingSymbolTable because its symbol look-ups are restricted to its
// DllHandle, but having libudev.so.0 resident may cause problems for that
// system library because symbol names are not namespaced by DLL.
LOG(LS_WARNING)
<< "libudev.so.1 is resident but distinct from libudev.so.0";
}
if (libudev_1) {
// Release the refcount that we acquired above. (Does not unload the DLL;
// whoever loaded it still needs it.)
dlclose(libudev_1);
}
return unsafe_symlink;
}
} // namespace cricket

View File

@@ -66,6 +66,14 @@ namespace cricket {
#undef LATE_BINDING_SYMBOL_TABLE_CLASS_NAME
#undef LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST
// libudev has changed ABIs to libudev.so.1 in recent distros and lots of users
// and/or software (including Google Chrome) are symlinking the old to the new.
// The entire point of ABI versions is that you can't safely do that, and
// it has caused crashes in the wild. This function checks if the DllHandle that
// we got back for libudev.so.0 is actually for libudev.so.1. If so, the library
// cannot safely be used.
bool IsWrongLibUDevAbiVersion(talk_base::DllHandle libudev_0);
} // namespace cricket
#endif // TALK_MEDIA_DEVICES_LIBUDEVSYMBOLTABLE_H_

View File

@@ -52,7 +52,8 @@ class ScopedLibUdev {
ScopedLibUdev() {}
bool Init() {
return libudev_.Load();
return libudev_.Load() &&
!IsWrongLibUDevAbiVersion(libudev_.GetDllHandle());
}
LibUDevSymbolTable libudev_;

View File

@@ -306,8 +306,9 @@ bool LinuxDeviceWatcher::Start() {
// We deliberately return true in the failure paths here because libudev is
// not a critical component of a Linux system so it may not be present/usable,
// and we don't want to halt LinuxDeviceManager initialization in such a case.
if (!libudev_.Load()) {
LOG(LS_WARNING) << "libudev not present/usable; LinuxDeviceWatcher disabled";
if (!libudev_.Load() || IsWrongLibUDevAbiVersion(libudev_.GetDllHandle())) {
LOG(LS_WARNING)
<< "libudev not present/usable; LinuxDeviceWatcher disabled";
return true;
}
udev_ = libudev_.udev_new()();

View File

@@ -242,8 +242,8 @@ DataMediaChannel* SctpDataEngine::CreateChannel(
SctpDataMediaChannel::SctpDataMediaChannel(talk_base::Thread* thread)
: worker_thread_(thread),
local_port_(kSctpDefaultPort),
remote_port_(kSctpDefaultPort),
local_port_(-1),
remote_port_(-1),
sock_(NULL),
sending_(false),
receiving_(false),
@@ -344,6 +344,12 @@ void SctpDataMediaChannel::CloseSctpSocket() {
bool SctpDataMediaChannel::Connect() {
LOG(LS_VERBOSE) << debug_name_ << "->Connect().";
if (remote_port_ < 0) {
remote_port_ = kSctpDefaultPort;
}
if (local_port_ < 0) {
local_port_ = kSctpDefaultPort;
}
// If we already have a socket connection, just return.
if (sock_) {
@@ -677,6 +683,38 @@ void SctpDataMediaChannel::OnNotificationAssocChange(
}
}
// Puts the specified |param| from the codec identified by |id| into |dest|
// and returns true. Or returns false if it wasn't there, leaving |dest|
// untouched.
static bool GetCodecIntParameter(const std::vector<DataCodec>& codecs,
int id, const std::string& name,
const std::string& param, int* dest) {
std::string value;
Codec match_pattern;
match_pattern.id = id;
match_pattern.name = name;
for (size_t i = 0; i < codecs.size(); ++i) {
if (codecs[i].Matches(match_pattern)) {
if (codecs[i].GetParam(param, &value)) {
*dest = talk_base::FromString<int>(value);
return true;
}
}
}
return false;
}
bool SctpDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) {
return GetCodecIntParameter(
codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort,
&remote_port_);
}
bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) {
return GetCodecIntParameter(
codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort,
&local_port_);
}
void SctpDataMediaChannel::OnPacketFromSctpToNetwork(
talk_base::Buffer* buffer) {

View File

@@ -168,12 +168,8 @@ class SctpDataMediaChannel : public DataMediaChannel,
const std::vector<RtpHeaderExtension>& extensions) { return true; }
virtual bool SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) { return true; }
virtual bool SetSendCodecs(const std::vector<DataCodec>& codecs) {
return true;
}
virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs) {
return true;
}
virtual bool SetSendCodecs(const std::vector<DataCodec>& codecs);
virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs);
virtual void OnRtcpReceived(talk_base::Buffer* packet) {}
virtual void OnReadyToSend(bool ready) {}
@@ -211,7 +207,8 @@ class SctpDataMediaChannel : public DataMediaChannel,
talk_base::Thread* worker_thread_;
// The local and remote SCTP port to use. These are passed along the wire
// and the listener and connector must be using the same port. It is not
// related to the ports at the IP level.
// related to the ports at the IP level. If set to -1, we default to
// kSctpDefaultPort.
int local_port_;
int remote_port_;
struct socket* sock_; // The socket created by usrsctp_socket(...).

View File

@@ -318,20 +318,32 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
virtual void IncomingRate(const int videoChannel,
const unsigned int framerate,
const unsigned int bitrate) {
talk_base::CritScope cs(&crit_);
ASSERT(video_channel_ == videoChannel);
framerate_ = framerate;
bitrate_ = bitrate;
}
virtual void RequestNewKeyFrame(const int videoChannel) {
talk_base::CritScope cs(&crit_);
ASSERT(video_channel_ == videoChannel);
++firs_requested_;
}
int framerate() const { return framerate_; }
int bitrate() const { return bitrate_; }
int firs_requested() const { return firs_requested_; }
int framerate() const {
talk_base::CritScope cs(&crit_);
return framerate_;
}
int bitrate() const {
talk_base::CritScope cs(&crit_);
return bitrate_;
}
int firs_requested() const {
talk_base::CritScope cs(&crit_);
return firs_requested_;
}
private:
mutable talk_base::CriticalSection crit_;
int video_channel_;
int framerate_;
int bitrate_;
@@ -350,15 +362,23 @@ class WebRtcEncoderObserver : public webrtc::ViEEncoderObserver {
virtual void OutgoingRate(const int videoChannel,
const unsigned int framerate,
const unsigned int bitrate) {
talk_base::CritScope cs(&crit_);
ASSERT(video_channel_ == videoChannel);
framerate_ = framerate;
bitrate_ = bitrate;
}
int framerate() const { return framerate_; }
int bitrate() const { return bitrate_; }
int framerate() const {
talk_base::CritScope cs(&crit_);
return framerate_;
}
int bitrate() const {
talk_base::CritScope cs(&crit_);
return bitrate_;
}
private:
mutable talk_base::CriticalSection crit_;
int video_channel_;
int framerate_;
int bitrate_;
@@ -914,6 +934,17 @@ bool WebRtcVideoEngine::SetDefaultEncoderConfig(
return SetDefaultCodec(config.max_codec);
}
VideoEncoderConfig WebRtcVideoEngine::GetDefaultEncoderConfig() const {
ASSERT(!video_codecs_.empty());
VideoCodec max_codec(kVideoCodecPrefs[0].payload_type,
kVideoCodecPrefs[0].name,
video_codecs_[0].width,
video_codecs_[0].height,
video_codecs_[0].framerate,
0);
return VideoEncoderConfig(max_codec);
}
// SetDefaultCodec may be called while the capturer is running. For example, a
// test call is started in a page with QVGA default codec, and then a real call
// is started in another page with VGA default codec. This is the corner case
@@ -924,6 +955,7 @@ bool WebRtcVideoEngine::SetDefaultCodec(const VideoCodec& codec) {
return false;
}
ASSERT(!video_codecs_.empty());
default_codec_format_ = VideoFormat(
video_codecs_[0].width,
video_codecs_[0].height,

View File

@@ -106,6 +106,7 @@ class WebRtcVideoEngine : public sigslot::has_slots<>,
int GetCapabilities();
bool SetOptions(const VideoOptions &options);
bool SetDefaultEncoderConfig(const VideoEncoderConfig& config);
VideoEncoderConfig GetDefaultEncoderConfig() const;
WebRtcVideoMediaChannel* CreateChannel(VoiceMediaChannel* voice_channel);

View File

@@ -2158,6 +2158,11 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
return false;
uint32 ssrc = sp.first_ssrc();
if (ssrc == 0) {
LOG(LS_WARNING) << "AddRecvStream with 0 ssrc is not supported.";
return false;
}
if (receive_channels_.find(ssrc) != receive_channels_.end()) {
LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
return false;
@@ -2181,6 +2186,21 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
return false;
}
if (!ConfigureRecvChannel(channel)) {
DeleteChannel(channel);
return false;
}
receive_channels_.insert(
std::make_pair(ssrc, WebRtcVoiceChannelInfo(channel, NULL)));
LOG(LS_INFO) << "New audio stream " << ssrc
<< " registered to VoiceEngine channel #"
<< channel << ".";
return true;
}
bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
// Configure to use external transport, like our default channel.
if (engine()->voe()->network()->RegisterExternalTransport(
channel, *this) == -1) {
@@ -2237,13 +2257,6 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
}
SetNack(channel, nack_enabled_);
receive_channels_.insert(
std::make_pair(ssrc, WebRtcVoiceChannelInfo(channel, NULL)));
// TODO(juberti): We should rollback the add if SetPlayout fails.
LOG(LS_INFO) << "New audio stream " << ssrc
<< " registered to VoiceEngine channel #"
<< channel << ".";
return SetPlayout(channel, playout_);
}

View File

@@ -381,6 +381,7 @@ class WebRtcVoiceMediaChannel
bool ChangeSend(SendFlags send);
bool ChangeSend(int channel, SendFlags send);
void ConfigureSendChannel(int channel);
bool ConfigureRecvChannel(int channel);
bool DeleteChannel(int channel);
bool InConferenceMode() const {
return options_.conference_mode.GetWithDefaultIfUnset(false);

View File

@@ -2044,6 +2044,26 @@ TEST_F(WebRtcVoiceEngineTestFake, StreamCleanup) {
EXPECT_EQ(0, voe_.GetNumChannels());
}
TEST_F(WebRtcVoiceEngineTestFake, TestAddRecvStreamFailWithZeroSsrc) {
EXPECT_TRUE(SetupEngine());
EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(0)));
}
TEST_F(WebRtcVoiceEngineTestFake, TestNoLeakingWhenAddRecvStreamFail) {
EXPECT_TRUE(SetupEngine());
// Stream 1 reuses default channel.
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
// Manually delete default channel to simulate a failure.
int default_channel = voe_.GetLastChannel();
EXPECT_EQ(0, voe_.DeleteChannel(default_channel));
// Add recv stream 2 should fail because default channel is gone.
EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
int new_channel = voe_.GetLastChannel();
EXPECT_NE(default_channel, new_channel);
// The last created channel should have already been deleted.
EXPECT_EQ(-1, voe_.DeleteChannel(new_channel));
}
// Test the InsertDtmf on default send stream as caller.
TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnDefaultSendStreamAsCaller) {
TestInsertDtmf(0, true);