Update libjingle to 55618622.
Update libyuv to r826. TEST=try bots R=niklas.enbom@webrtc.org Review URL: https://webrtc-codereview.appspot.com/2889004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5038 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
728bc0fa4c
commit
97077a3ab2
2
DEPS
2
DEPS
@ -72,7 +72,7 @@ deps = {
|
|||||||
Var("chromium_trunk") + "/deps/third_party/libvpx@225010",
|
Var("chromium_trunk") + "/deps/third_party/libvpx@225010",
|
||||||
|
|
||||||
"third_party/libyuv":
|
"third_party/libyuv":
|
||||||
(Var("googlecode_url") % "libyuv") + "/trunk@723",
|
(Var("googlecode_url") % "libyuv") + "/trunk@826",
|
||||||
|
|
||||||
"third_party/opus":
|
"third_party/opus":
|
||||||
Var("chromium_trunk") + "/src/third_party/opus@185405",
|
Var("chromium_trunk") + "/src/third_party/opus@185405",
|
||||||
|
@ -53,7 +53,9 @@ const char MediaConstraintsInterface::kHighpassFilter[] =
|
|||||||
"googHighpassFilter";
|
"googHighpassFilter";
|
||||||
const char MediaConstraintsInterface::kTypingNoiseDetection[] =
|
const char MediaConstraintsInterface::kTypingNoiseDetection[] =
|
||||||
"googTypingNoiseDetection";
|
"googTypingNoiseDetection";
|
||||||
const char MediaConstraintsInterface::kInternalAecDump[] = "internalAecDump";
|
const char MediaConstraintsInterface::kAudioMirroring[] = "googAudioMirroring";
|
||||||
|
// TODO(perkj): Remove kInternalAecDump once its not used by Chrome.
|
||||||
|
const char MediaConstraintsInterface::kInternalAecDump[] = "deprecatedAecDump";
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -90,10 +92,10 @@ bool FromConstraints(const MediaConstraintsInterface::Constraints& constraints,
|
|||||||
options->noise_suppression.Set(value);
|
options->noise_suppression.Set(value);
|
||||||
else if (iter->key == MediaConstraintsInterface::kHighpassFilter)
|
else if (iter->key == MediaConstraintsInterface::kHighpassFilter)
|
||||||
options->highpass_filter.Set(value);
|
options->highpass_filter.Set(value);
|
||||||
else if (iter->key == MediaConstraintsInterface::kInternalAecDump)
|
|
||||||
options->aec_dump.Set(value);
|
|
||||||
else if (iter->key == MediaConstraintsInterface::kTypingNoiseDetection)
|
else if (iter->key == MediaConstraintsInterface::kTypingNoiseDetection)
|
||||||
options->typing_detection.Set(value);
|
options->typing_detection.Set(value);
|
||||||
|
else if (iter->key == MediaConstraintsInterface::kAudioMirroring)
|
||||||
|
options->stereo_swapping.Set(value);
|
||||||
else
|
else
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@ -103,14 +105,16 @@ bool FromConstraints(const MediaConstraintsInterface::Constraints& constraints,
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
talk_base::scoped_refptr<LocalAudioSource> LocalAudioSource::Create(
|
talk_base::scoped_refptr<LocalAudioSource> LocalAudioSource::Create(
|
||||||
|
const PeerConnectionFactoryInterface::Options& options,
|
||||||
const MediaConstraintsInterface* constraints) {
|
const MediaConstraintsInterface* constraints) {
|
||||||
talk_base::scoped_refptr<LocalAudioSource> source(
|
talk_base::scoped_refptr<LocalAudioSource> source(
|
||||||
new talk_base::RefCountedObject<LocalAudioSource>());
|
new talk_base::RefCountedObject<LocalAudioSource>());
|
||||||
source->Initialize(constraints);
|
source->Initialize(options, constraints);
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalAudioSource::Initialize(
|
void LocalAudioSource::Initialize(
|
||||||
|
const PeerConnectionFactoryInterface::Options& options,
|
||||||
const MediaConstraintsInterface* constraints) {
|
const MediaConstraintsInterface* constraints) {
|
||||||
if (!constraints)
|
if (!constraints)
|
||||||
return;
|
return;
|
||||||
@ -119,12 +123,14 @@ void LocalAudioSource::Initialize(
|
|||||||
// constraints.
|
// constraints.
|
||||||
FromConstraints(constraints->GetOptional(), &options_);
|
FromConstraints(constraints->GetOptional(), &options_);
|
||||||
|
|
||||||
cricket::AudioOptions options;
|
cricket::AudioOptions audio_options;
|
||||||
if (!FromConstraints(constraints->GetMandatory(), &options)) {
|
if (!FromConstraints(constraints->GetMandatory(), &audio_options)) {
|
||||||
source_state_ = kEnded;
|
source_state_ = kEnded;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
options_.SetAll(options);
|
options_.SetAll(audio_options);
|
||||||
|
if (options.enable_aec_dump)
|
||||||
|
options_.aec_dump.Set(true);
|
||||||
source_state_ = kLive;
|
source_state_ = kLive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "talk/app/webrtc/mediastreaminterface.h"
|
#include "talk/app/webrtc/mediastreaminterface.h"
|
||||||
#include "talk/app/webrtc/notifier.h"
|
#include "talk/app/webrtc/notifier.h"
|
||||||
|
#include "talk/app/webrtc/peerconnectioninterface.h"
|
||||||
#include "talk/base/scoped_ptr.h"
|
#include "talk/base/scoped_ptr.h"
|
||||||
#include "talk/media/base/mediachannel.h"
|
#include "talk/media/base/mediachannel.h"
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ class LocalAudioSource : public Notifier<AudioSourceInterface> {
|
|||||||
public:
|
public:
|
||||||
// Creates an instance of LocalAudioSource.
|
// Creates an instance of LocalAudioSource.
|
||||||
static talk_base::scoped_refptr<LocalAudioSource> Create(
|
static talk_base::scoped_refptr<LocalAudioSource> Create(
|
||||||
|
const PeerConnectionFactoryInterface::Options& options,
|
||||||
const MediaConstraintsInterface* constraints);
|
const MediaConstraintsInterface* constraints);
|
||||||
|
|
||||||
virtual SourceState state() const { return source_state_; }
|
virtual SourceState state() const { return source_state_; }
|
||||||
@ -58,7 +60,8 @@ class LocalAudioSource : public Notifier<AudioSourceInterface> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Initialize(const MediaConstraintsInterface* constraints);
|
void Initialize(const PeerConnectionFactoryInterface::Options& options,
|
||||||
|
const MediaConstraintsInterface* constraints);
|
||||||
|
|
||||||
cricket::AudioOptions options_;
|
cricket::AudioOptions options_;
|
||||||
SourceState source_state_;
|
SourceState source_state_;
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
using webrtc::LocalAudioSource;
|
using webrtc::LocalAudioSource;
|
||||||
using webrtc::MediaConstraintsInterface;
|
using webrtc::MediaConstraintsInterface;
|
||||||
using webrtc::MediaSourceInterface;
|
using webrtc::MediaSourceInterface;
|
||||||
|
using webrtc::PeerConnectionFactoryInterface;
|
||||||
|
|
||||||
TEST(LocalAudioSourceTest, SetValidOptions) {
|
TEST(LocalAudioSourceTest, SetValidOptions) {
|
||||||
webrtc::FakeConstraints constraints;
|
webrtc::FakeConstraints constraints;
|
||||||
@ -52,7 +53,8 @@ TEST(LocalAudioSourceTest, SetValidOptions) {
|
|||||||
constraints.AddOptional(MediaConstraintsInterface::kHighpassFilter, true);
|
constraints.AddOptional(MediaConstraintsInterface::kHighpassFilter, true);
|
||||||
|
|
||||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||||
LocalAudioSource::Create(&constraints);
|
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||||
|
&constraints);
|
||||||
|
|
||||||
bool value;
|
bool value;
|
||||||
EXPECT_TRUE(source->options().echo_cancellation.Get(&value));
|
EXPECT_TRUE(source->options().echo_cancellation.Get(&value));
|
||||||
@ -72,7 +74,8 @@ TEST(LocalAudioSourceTest, SetValidOptions) {
|
|||||||
TEST(LocalAudioSourceTest, OptionNotSet) {
|
TEST(LocalAudioSourceTest, OptionNotSet) {
|
||||||
webrtc::FakeConstraints constraints;
|
webrtc::FakeConstraints constraints;
|
||||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||||
LocalAudioSource::Create(&constraints);
|
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||||
|
&constraints);
|
||||||
bool value;
|
bool value;
|
||||||
EXPECT_FALSE(source->options().highpass_filter.Get(&value));
|
EXPECT_FALSE(source->options().highpass_filter.Get(&value));
|
||||||
}
|
}
|
||||||
@ -83,7 +86,8 @@ TEST(LocalAudioSourceTest, MandatoryOverridesOptional) {
|
|||||||
constraints.AddOptional(MediaConstraintsInterface::kEchoCancellation, true);
|
constraints.AddOptional(MediaConstraintsInterface::kEchoCancellation, true);
|
||||||
|
|
||||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||||
LocalAudioSource::Create(&constraints);
|
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||||
|
&constraints);
|
||||||
|
|
||||||
bool value;
|
bool value;
|
||||||
EXPECT_TRUE(source->options().echo_cancellation.Get(&value));
|
EXPECT_TRUE(source->options().echo_cancellation.Get(&value));
|
||||||
@ -96,7 +100,8 @@ TEST(LocalAudioSourceTest, InvalidOptional) {
|
|||||||
constraints.AddOptional("invalidKey", false);
|
constraints.AddOptional("invalidKey", false);
|
||||||
|
|
||||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||||
LocalAudioSource::Create(&constraints);
|
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||||
|
&constraints);
|
||||||
|
|
||||||
EXPECT_EQ(MediaSourceInterface::kLive, source->state());
|
EXPECT_EQ(MediaSourceInterface::kLive, source->state());
|
||||||
bool value;
|
bool value;
|
||||||
@ -110,7 +115,8 @@ TEST(LocalAudioSourceTest, InvalidMandatory) {
|
|||||||
constraints.AddMandatory("invalidKey", false);
|
constraints.AddMandatory("invalidKey", false);
|
||||||
|
|
||||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||||
LocalAudioSource::Create(&constraints);
|
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||||
|
&constraints);
|
||||||
|
|
||||||
EXPECT_EQ(MediaSourceInterface::kEnded, source->state());
|
EXPECT_EQ(MediaSourceInterface::kEnded, source->state());
|
||||||
bool value;
|
bool value;
|
||||||
|
@ -81,6 +81,7 @@ class MediaConstraintsInterface {
|
|||||||
static const char kNoiseSuppression[]; // googNoiseSuppression
|
static const char kNoiseSuppression[]; // googNoiseSuppression
|
||||||
static const char kHighpassFilter[]; // googHighpassFilter
|
static const char kHighpassFilter[]; // googHighpassFilter
|
||||||
static const char kTypingNoiseDetection[]; // googTypingNoiseDetection
|
static const char kTypingNoiseDetection[]; // googTypingNoiseDetection
|
||||||
|
static const char kAudioMirroring[]; // googAudioMirroring
|
||||||
|
|
||||||
// Google-specific constraint keys for a local video source
|
// Google-specific constraint keys for a local video source
|
||||||
static const char kNoiseReduction[]; // googNoiseReduction
|
static const char kNoiseReduction[]; // googNoiseReduction
|
||||||
@ -106,6 +107,8 @@ class MediaConstraintsInterface {
|
|||||||
static const char kEnableDtlsSrtp[]; // Enable DTLS-SRTP
|
static const char kEnableDtlsSrtp[]; // Enable DTLS-SRTP
|
||||||
// Temporary pseudo-constraints used to enable DataChannels
|
// Temporary pseudo-constraints used to enable DataChannels
|
||||||
static const char kEnableRtpDataChannels[]; // Enable RTP DataChannels
|
static const char kEnableRtpDataChannels[]; // Enable RTP DataChannels
|
||||||
|
// TODO(perkj): Remove kEnableSctpDataChannels once Chrome use
|
||||||
|
// PeerConnectionFactory::SetOptions.
|
||||||
static const char kEnableSctpDataChannels[]; // Enable SCTP DataChannels
|
static const char kEnableSctpDataChannels[]; // Enable SCTP DataChannels
|
||||||
|
|
||||||
// The prefix of internal-only constraints whose JS set values should be
|
// The prefix of internal-only constraints whose JS set values should be
|
||||||
@ -116,9 +119,8 @@ class MediaConstraintsInterface {
|
|||||||
// line flags. So they are prefixed with "internal" so JS values will be
|
// line flags. So they are prefixed with "internal" so JS values will be
|
||||||
// removed.
|
// removed.
|
||||||
// Used by a local audio source.
|
// Used by a local audio source.
|
||||||
|
// TODO(perkj): Remove once Chrome use PeerConnectionFactory::SetOptions.
|
||||||
static const char kInternalAecDump[]; // internalAecDump
|
static const char kInternalAecDump[]; // internalAecDump
|
||||||
// Used for disabling security and use plain RTP.
|
|
||||||
static const char kInternalDisableEncryption[]; // internalDisableEncryption
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Dtor protected as objects shouldn't be deleted via this interface
|
// Dtor protected as objects shouldn't be deleted via this interface
|
||||||
|
@ -267,6 +267,10 @@ bool MediaStreamSignaling::AddDataChannelFromOpenMessage(
|
|||||||
}
|
}
|
||||||
scoped_refptr<DataChannel> channel(
|
scoped_refptr<DataChannel> channel(
|
||||||
data_channel_factory_->CreateDataChannel(label, &config));
|
data_channel_factory_->CreateDataChannel(label, &config));
|
||||||
|
if (!channel.get()) {
|
||||||
|
LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
data_channels_[label] = channel;
|
data_channels_[label] = channel;
|
||||||
stream_observer_->OnAddDataChannel(channel);
|
stream_observer_->OnAddDataChannel(channel);
|
||||||
// It's immediately ready to use.
|
// It's immediately ready to use.
|
||||||
|
@ -317,7 +317,8 @@ bool PeerConnection::DoInitialize(
|
|||||||
stats_.set_session(session_.get());
|
stats_.set_session(session_.get());
|
||||||
|
|
||||||
// Initialize the WebRtcSession. It creates transport channels etc.
|
// Initialize the WebRtcSession. It creates transport channels etc.
|
||||||
if (!session_->Initialize(constraints, dtls_identity_service))
|
if (!session_->Initialize(factory_->options(), constraints,
|
||||||
|
dtls_identity_service))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Register PeerConnection as receiver of local ice candidates.
|
// Register PeerConnection as receiver of local ice candidates.
|
||||||
|
@ -157,8 +157,8 @@ class PeerConnectionTestClientBase
|
|||||||
// Disable highpass filter so that we can get all the test audio frames.
|
// Disable highpass filter so that we can get all the test audio frames.
|
||||||
constraints.AddMandatory(
|
constraints.AddMandatory(
|
||||||
MediaConstraintsInterface::kHighpassFilter, false);
|
MediaConstraintsInterface::kHighpassFilter, false);
|
||||||
talk_base::scoped_refptr<webrtc::LocalAudioSource> source =
|
talk_base::scoped_refptr<webrtc::AudioSourceInterface> source =
|
||||||
webrtc::LocalAudioSource::Create(&constraints);
|
peer_connection_factory_->CreateAudioSource(&constraints);
|
||||||
// TODO(perkj): Test audio source when it is implemented. Currently audio
|
// TODO(perkj): Test audio source when it is implemented. Currently audio
|
||||||
// always use the default input.
|
// always use the default input.
|
||||||
talk_base::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
|
talk_base::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
|
||||||
|
@ -261,7 +261,7 @@ talk_base::scoped_refptr<AudioSourceInterface>
|
|||||||
PeerConnectionFactory::CreateAudioSource_s(
|
PeerConnectionFactory::CreateAudioSource_s(
|
||||||
const MediaConstraintsInterface* constraints) {
|
const MediaConstraintsInterface* constraints) {
|
||||||
talk_base::scoped_refptr<LocalAudioSource> source(
|
talk_base::scoped_refptr<LocalAudioSource> source(
|
||||||
LocalAudioSource::Create(constraints));
|
LocalAudioSource::Create(options_, constraints));
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,10 @@ namespace webrtc {
|
|||||||
class PeerConnectionFactory : public PeerConnectionFactoryInterface,
|
class PeerConnectionFactory : public PeerConnectionFactoryInterface,
|
||||||
public talk_base::MessageHandler {
|
public talk_base::MessageHandler {
|
||||||
public:
|
public:
|
||||||
|
virtual void SetOptions(const Options& options) {
|
||||||
|
options_ = options;
|
||||||
|
}
|
||||||
|
|
||||||
virtual talk_base::scoped_refptr<PeerConnectionInterface>
|
virtual talk_base::scoped_refptr<PeerConnectionInterface>
|
||||||
CreatePeerConnection(
|
CreatePeerConnection(
|
||||||
const PeerConnectionInterface::IceServers& configuration,
|
const PeerConnectionInterface::IceServers& configuration,
|
||||||
@ -77,6 +81,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface,
|
|||||||
virtual cricket::ChannelManager* channel_manager();
|
virtual cricket::ChannelManager* channel_manager();
|
||||||
virtual talk_base::Thread* signaling_thread();
|
virtual talk_base::Thread* signaling_thread();
|
||||||
virtual talk_base::Thread* worker_thread();
|
virtual talk_base::Thread* worker_thread();
|
||||||
|
const Options& options() const { return options_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PeerConnectionFactory();
|
PeerConnectionFactory();
|
||||||
@ -109,6 +114,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface,
|
|||||||
bool owns_ptrs_;
|
bool owns_ptrs_;
|
||||||
talk_base::Thread* signaling_thread_;
|
talk_base::Thread* signaling_thread_;
|
||||||
talk_base::Thread* worker_thread_;
|
talk_base::Thread* worker_thread_;
|
||||||
|
Options options_;
|
||||||
talk_base::scoped_refptr<PortAllocatorFactoryInterface> allocator_factory_;
|
talk_base::scoped_refptr<PortAllocatorFactoryInterface> allocator_factory_;
|
||||||
// External Audio device used for audio playback.
|
// External Audio device used for audio playback.
|
||||||
talk_base::scoped_refptr<AudioDeviceModule> default_adm_;
|
talk_base::scoped_refptr<AudioDeviceModule> default_adm_;
|
||||||
|
@ -390,6 +390,19 @@ class DTLSIdentityServiceInterface {
|
|||||||
// argument.
|
// argument.
|
||||||
class PeerConnectionFactoryInterface : public talk_base::RefCountInterface {
|
class PeerConnectionFactoryInterface : public talk_base::RefCountInterface {
|
||||||
public:
|
public:
|
||||||
|
class Options {
|
||||||
|
public:
|
||||||
|
Options() :
|
||||||
|
enable_aec_dump(false),
|
||||||
|
disable_encryption(false),
|
||||||
|
disable_sctp_data_channels(false) {
|
||||||
|
}
|
||||||
|
bool enable_aec_dump;
|
||||||
|
bool disable_encryption;
|
||||||
|
bool disable_sctp_data_channels;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void SetOptions(const Options& options) = 0;
|
||||||
virtual talk_base::scoped_refptr<PeerConnectionInterface>
|
virtual talk_base::scoped_refptr<PeerConnectionInterface>
|
||||||
CreatePeerConnection(
|
CreatePeerConnection(
|
||||||
const PeerConnectionInterface::IceServers& configuration,
|
const PeerConnectionInterface::IceServers& configuration,
|
||||||
|
@ -82,6 +82,15 @@ const char StatsReport::kStatsValueNameFrameRateDecoded[] =
|
|||||||
"googFrameRateDecoded";
|
"googFrameRateDecoded";
|
||||||
const char StatsReport::kStatsValueNameFrameRateOutput[] =
|
const char StatsReport::kStatsValueNameFrameRateOutput[] =
|
||||||
"googFrameRateOutput";
|
"googFrameRateOutput";
|
||||||
|
const char StatsReport::kStatsValueNameDecodeMs[] = "googDecodeMs";
|
||||||
|
const char StatsReport::kStatsValueNameMaxDecodeMs[] = "googMaxDecodeMs";
|
||||||
|
const char StatsReport::kStatsValueNameCurrentDelayMs[] = "googCurrentDelayMs";
|
||||||
|
const char StatsReport::kStatsValueNameTargetDelayMs[] = "googTargetDelayMs";
|
||||||
|
const char StatsReport::kStatsValueNameJitterBufferMs[] = "googJitterBufferMs";
|
||||||
|
const char StatsReport::kStatsValueNameMinPlayoutDelayMs[] =
|
||||||
|
"googMinPlayoutDelayMs";
|
||||||
|
const char StatsReport::kStatsValueNameRenderDelayMs[] = "googRenderDelayMs";
|
||||||
|
|
||||||
const char StatsReport::kStatsValueNameFrameRateInput[] = "googFrameRateInput";
|
const char StatsReport::kStatsValueNameFrameRateInput[] = "googFrameRateInput";
|
||||||
const char StatsReport::kStatsValueNameFrameRateSent[] = "googFrameRateSent";
|
const char StatsReport::kStatsValueNameFrameRateSent[] = "googFrameRateSent";
|
||||||
const char StatsReport::kStatsValueNameFrameWidthReceived[] =
|
const char StatsReport::kStatsValueNameFrameWidthReceived[] =
|
||||||
@ -119,6 +128,7 @@ const char StatsReport::kStatsValueNameWritable[] = "googWritable";
|
|||||||
|
|
||||||
const char StatsReport::kStatsReportTypeSession[] = "googLibjingleSession";
|
const char StatsReport::kStatsReportTypeSession[] = "googLibjingleSession";
|
||||||
const char StatsReport::kStatsReportTypeBwe[] = "VideoBwe";
|
const char StatsReport::kStatsReportTypeBwe[] = "VideoBwe";
|
||||||
|
const char StatsReport::kStatsReportTypeRemoteSsrc[] = "remoteSsrc";
|
||||||
const char StatsReport::kStatsReportTypeSsrc[] = "ssrc";
|
const char StatsReport::kStatsReportTypeSsrc[] = "ssrc";
|
||||||
const char StatsReport::kStatsReportTypeTrack[] = "googTrack";
|
const char StatsReport::kStatsReportTypeTrack[] = "googTrack";
|
||||||
const char StatsReport::kStatsReportTypeIceCandidate[] = "iceCandidate";
|
const char StatsReport::kStatsReportTypeIceCandidate[] = "iceCandidate";
|
||||||
@ -241,6 +251,21 @@ void ExtractStats(const cricket::VideoReceiverInfo& info, StatsReport* report) {
|
|||||||
info.framerate_decoded);
|
info.framerate_decoded);
|
||||||
report->AddValue(StatsReport::kStatsValueNameFrameRateOutput,
|
report->AddValue(StatsReport::kStatsValueNameFrameRateOutput,
|
||||||
info.framerate_output);
|
info.framerate_output);
|
||||||
|
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameDecodeMs,
|
||||||
|
info.decode_ms);
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameMaxDecodeMs,
|
||||||
|
info.max_decode_ms);
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameCurrentDelayMs,
|
||||||
|
info.current_delay_ms);
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameTargetDelayMs,
|
||||||
|
info.target_delay_ms);
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameJitterBufferMs,
|
||||||
|
info.jitter_buffer_ms);
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameMinPlayoutDelayMs,
|
||||||
|
info.min_playout_delay_ms);
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameRenderDelayMs,
|
||||||
|
info.render_delay_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractStats(const cricket::VideoSenderInfo& info, StatsReport* report) {
|
void ExtractStats(const cricket::VideoSenderInfo& info, StatsReport* report) {
|
||||||
@ -293,6 +318,18 @@ void ExtractStats(const cricket::BandwidthEstimationInfo& info,
|
|||||||
info.bucket_delay);
|
info.bucket_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExtractRemoteStats(const cricket::MediaSenderInfo& info,
|
||||||
|
StatsReport* report) {
|
||||||
|
report->timestamp = info.remote_stats[0].timestamp;
|
||||||
|
// TODO(hta): Extract some stats here.
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtractRemoteStats(const cricket::MediaReceiverInfo& info,
|
||||||
|
StatsReport* report) {
|
||||||
|
report->timestamp = info.remote_stats[0].timestamp;
|
||||||
|
// TODO(hta): Extract some stats here.
|
||||||
|
}
|
||||||
|
|
||||||
uint32 ExtractSsrc(const cricket::VoiceReceiverInfo& info) {
|
uint32 ExtractSsrc(const cricket::VoiceReceiverInfo& info) {
|
||||||
return info.ssrc;
|
return info.ssrc;
|
||||||
}
|
}
|
||||||
@ -319,11 +356,20 @@ void ExtractStatsFromList(const std::vector<T>& data,
|
|||||||
for (; it != data.end(); ++it) {
|
for (; it != data.end(); ++it) {
|
||||||
std::string id;
|
std::string id;
|
||||||
uint32 ssrc = ExtractSsrc(*it);
|
uint32 ssrc = ExtractSsrc(*it);
|
||||||
StatsReport* report = collector->PrepareReport(ssrc, transport_id);
|
// Each object can result in 2 objects, a local and a remote object.
|
||||||
|
// TODO(hta): Handle the case of multiple SSRCs per object.
|
||||||
|
StatsReport* report = collector->PrepareLocalReport(ssrc, transport_id);
|
||||||
if (!report) {
|
if (!report) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ExtractStats(*it, report);
|
ExtractStats(*it, report);
|
||||||
|
if (it->remote_stats.size() > 0) {
|
||||||
|
report = collector->PrepareRemoteReport(ssrc, transport_id);
|
||||||
|
if (!report) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ExtractRemoteStats(*it, report);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -406,7 +452,8 @@ void StatsCollector::UpdateStats() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
|
StatsReport* StatsCollector::PrepareLocalReport(
|
||||||
|
uint32 ssrc,
|
||||||
const std::string& transport_id) {
|
const std::string& transport_id) {
|
||||||
std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
|
std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
|
||||||
StatsMap::iterator it = reports_.find(StatsId(
|
StatsMap::iterator it = reports_.find(StatsId(
|
||||||
@ -427,10 +474,8 @@ StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
|
|||||||
&track_id);
|
&track_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
StatsReport* report = &reports_[
|
StatsReport* report = GetOrCreateReport(StatsReport::kStatsReportTypeSsrc,
|
||||||
StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id)];
|
ssrc_id);
|
||||||
report->id = StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id);
|
|
||||||
report->type = StatsReport::kStatsReportTypeSsrc;
|
|
||||||
|
|
||||||
// Clear out stats from previous GatherStats calls if any.
|
// Clear out stats from previous GatherStats calls if any.
|
||||||
if (report->timestamp != stats_gathering_started_) {
|
if (report->timestamp != stats_gathering_started_) {
|
||||||
@ -446,6 +491,44 @@ StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
|
|||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatsReport* StatsCollector::PrepareRemoteReport(
|
||||||
|
uint32 ssrc,
|
||||||
|
const std::string& transport_id) {
|
||||||
|
std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
|
||||||
|
StatsMap::iterator it = reports_.find(StatsId(
|
||||||
|
StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id));
|
||||||
|
|
||||||
|
std::string track_id;
|
||||||
|
if (it == reports_.end()) {
|
||||||
|
if (!session()->GetTrackIdBySsrc(ssrc, &track_id)) {
|
||||||
|
LOG(LS_WARNING) << "The SSRC " << ssrc
|
||||||
|
<< " is not associated with a track";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Keeps the old track id since we want to report the stats for inactive
|
||||||
|
// tracks.
|
||||||
|
ExtractValueFromReport(it->second,
|
||||||
|
StatsReport::kStatsValueNameTrackId,
|
||||||
|
&track_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
StatsReport* report = GetOrCreateReport(
|
||||||
|
StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id);
|
||||||
|
|
||||||
|
// Clear out stats from previous GatherStats calls if any.
|
||||||
|
// The timestamp will be added later. Zero it for debugging.
|
||||||
|
report->values.clear();
|
||||||
|
report->timestamp = 0;
|
||||||
|
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameSsrc, ssrc_id);
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameTrackId, track_id);
|
||||||
|
// Add the mapping of SSRC to transport.
|
||||||
|
report->AddValue(StatsReport::kStatsValueNameTransportId,
|
||||||
|
transport_id);
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
std::string StatsCollector::AddOneCertificateReport(
|
std::string StatsCollector::AddOneCertificateReport(
|
||||||
const talk_base::SSLCertificate* cert, const std::string& issuer_id) {
|
const talk_base::SSLCertificate* cert, const std::string& issuer_id) {
|
||||||
// TODO(bemasc): Move this computation to a helper class that caches these
|
// TODO(bemasc): Move this computation to a helper class that caches these
|
||||||
@ -592,6 +675,9 @@ void StatsCollector::ExtractSessionInfo() {
|
|||||||
info.local_candidate.address().ToString());
|
info.local_candidate.address().ToString());
|
||||||
report.AddValue(StatsReport::kStatsValueNameRemoteAddress,
|
report.AddValue(StatsReport::kStatsValueNameRemoteAddress,
|
||||||
info.remote_candidate.address().ToString());
|
info.remote_candidate.address().ToString());
|
||||||
|
report.AddValue(StatsReport::kStatsValueNameRtt, info.rtt);
|
||||||
|
report.AddValue(StatsReport::kStatsValueNameTransportType,
|
||||||
|
info.local_candidate.protocol());
|
||||||
reports_[report.id] = report;
|
reports_[report.id] = report;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -668,4 +754,19 @@ bool StatsCollector::GetTransportIdFromProxy(const std::string& proxy,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatsReport* StatsCollector::GetOrCreateReport(const std::string& type,
|
||||||
|
const std::string& id) {
|
||||||
|
std::string statsid = StatsId(type, id);
|
||||||
|
StatsReport* report = NULL;
|
||||||
|
std::map<std::string, StatsReport>::iterator it = reports_.find(statsid);
|
||||||
|
if (it == reports_.end()) {
|
||||||
|
report = &reports_[statsid]; // Create new element.
|
||||||
|
report->id = statsid;
|
||||||
|
report->type = type;
|
||||||
|
} else {
|
||||||
|
report = &reports_[statsid];
|
||||||
|
}
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -65,9 +65,11 @@ class StatsCollector {
|
|||||||
// |reports|.
|
// |reports|.
|
||||||
bool GetStats(MediaStreamTrackInterface* track, StatsReports* reports);
|
bool GetStats(MediaStreamTrackInterface* track, StatsReports* reports);
|
||||||
|
|
||||||
WebRtcSession* session() { return session_; }
|
// Prepare an SSRC report for the given ssrc. Used internally
|
||||||
// Prepare an SSRC report for the given ssrc. Used internally.
|
// in the ExtractStatsFromList template.
|
||||||
StatsReport* PrepareReport(uint32 ssrc, const std::string& transport);
|
StatsReport* PrepareLocalReport(uint32 ssrc, const std::string& transport);
|
||||||
|
// Prepare an SSRC report for the given remote ssrc. Used internally.
|
||||||
|
StatsReport* PrepareRemoteReport(uint32 ssrc, const std::string& transport);
|
||||||
// Extracts the ID of a Transport belonging to an SSRC. Used internally.
|
// Extracts the ID of a Transport belonging to an SSRC. Used internally.
|
||||||
bool GetTransportIdFromProxy(const std::string& proxy,
|
bool GetTransportIdFromProxy(const std::string& proxy,
|
||||||
std::string* transport_id);
|
std::string* transport_id);
|
||||||
@ -88,9 +90,12 @@ class StatsCollector {
|
|||||||
void ExtractVideoInfo();
|
void ExtractVideoInfo();
|
||||||
double GetTimeNow();
|
double GetTimeNow();
|
||||||
void BuildSsrcToTransportId();
|
void BuildSsrcToTransportId();
|
||||||
|
WebRtcSession* session() { return session_; }
|
||||||
|
webrtc::StatsReport* GetOrCreateReport(const std::string& type,
|
||||||
|
const std::string& id);
|
||||||
|
|
||||||
// A map from the report id to the report.
|
// A map from the report id to the report.
|
||||||
std::map<std::string, webrtc::StatsReport> reports_;
|
std::map<std::string, StatsReport> reports_;
|
||||||
// Raw pointer to the session the statistics are gathered from.
|
// Raw pointer to the session the statistics are gathered from.
|
||||||
WebRtcSession* session_;
|
WebRtcSession* session_;
|
||||||
double stats_gathering_started_;
|
double stats_gathering_started_;
|
||||||
|
@ -58,6 +58,10 @@ namespace {
|
|||||||
const char kNotFound[] = "NOT FOUND";
|
const char kNotFound[] = "NOT FOUND";
|
||||||
const char kNoReports[] = "NO REPORTS";
|
const char kNoReports[] = "NO REPORTS";
|
||||||
|
|
||||||
|
// Constant names for track identification.
|
||||||
|
const char kTrackId[] = "somename";
|
||||||
|
const uint32 kSsrcOfTrack = 1234;
|
||||||
|
|
||||||
class MockWebRtcSession : public webrtc::WebRtcSession {
|
class MockWebRtcSession : public webrtc::WebRtcSession {
|
||||||
public:
|
public:
|
||||||
explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
|
explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
|
||||||
@ -207,11 +211,37 @@ class StatsCollectorTest : public testing::Test {
|
|||||||
new cricket::ChannelManager(media_engine_,
|
new cricket::ChannelManager(media_engine_,
|
||||||
new cricket::FakeDeviceManager(),
|
new cricket::FakeDeviceManager(),
|
||||||
talk_base::Thread::Current())),
|
talk_base::Thread::Current())),
|
||||||
session_(channel_manager_.get()) {
|
session_(channel_manager_.get()),
|
||||||
|
track_id_(kTrackId) {
|
||||||
// By default, we ignore session GetStats calls.
|
// By default, we ignore session GetStats calls.
|
||||||
EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
|
EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This creates a standard setup with a transport called "trspname"
|
||||||
|
// having one transport channel
|
||||||
|
// and the specified virtual connection name.
|
||||||
|
void InitSessionStats(const std::string vc_name) {
|
||||||
|
const std::string kTransportName("trspname");
|
||||||
|
cricket::TransportStats transport_stats;
|
||||||
|
cricket::TransportChannelStats channel_stats;
|
||||||
|
channel_stats.component = 1;
|
||||||
|
transport_stats.content_name = kTransportName;
|
||||||
|
transport_stats.channel_stats.push_back(channel_stats);
|
||||||
|
|
||||||
|
session_stats_.transport_stats[kTransportName] = transport_stats;
|
||||||
|
session_stats_.proxy_to_transport[vc_name] = kTransportName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a track with a given SSRC into the stats.
|
||||||
|
void AddVideoTrackStats() {
|
||||||
|
stream_ = webrtc::MediaStream::Create("streamlabel");
|
||||||
|
track_= webrtc::VideoTrack::Create(kTrackId, NULL);
|
||||||
|
stream_->AddTrack(track_);
|
||||||
|
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
||||||
|
.WillRepeatedly(DoAll(SetArgPointee<1>(track_id_),
|
||||||
|
Return(true)));
|
||||||
|
}
|
||||||
|
|
||||||
void TestCertificateReports(const talk_base::FakeSSLCertificate& local_cert,
|
void TestCertificateReports(const talk_base::FakeSSLCertificate& local_cert,
|
||||||
const std::vector<std::string>& local_ders,
|
const std::vector<std::string>& local_ders,
|
||||||
const talk_base::FakeSSLCertificate& remote_cert,
|
const talk_base::FakeSSLCertificate& remote_cert,
|
||||||
@ -283,9 +313,14 @@ class StatsCollectorTest : public testing::Test {
|
|||||||
EXPECT_NE(kNotFound, remote_certificate_id);
|
EXPECT_NE(kNotFound, remote_certificate_id);
|
||||||
CheckCertChainReports(reports, remote_ders, remote_certificate_id);
|
CheckCertChainReports(reports, remote_ders, remote_certificate_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
cricket::FakeMediaEngine* media_engine_;
|
cricket::FakeMediaEngine* media_engine_;
|
||||||
talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
|
talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
|
||||||
MockWebRtcSession session_;
|
MockWebRtcSession session_;
|
||||||
|
cricket::SessionStats session_stats_;
|
||||||
|
talk_base::scoped_refptr<webrtc::MediaStream> stream_;
|
||||||
|
talk_base::scoped_refptr<webrtc::VideoTrack> track_;
|
||||||
|
std::string track_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This test verifies that 64-bit counters are passed successfully.
|
// This test verifies that 64-bit counters are passed successfully.
|
||||||
@ -297,17 +332,13 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
|
|||||||
webrtc::StatsReports reports; // returned values.
|
webrtc::StatsReports reports; // returned values.
|
||||||
cricket::VideoSenderInfo video_sender_info;
|
cricket::VideoSenderInfo video_sender_info;
|
||||||
cricket::VideoMediaInfo stats_read;
|
cricket::VideoMediaInfo stats_read;
|
||||||
const uint32 kSsrcOfTrack = 1234;
|
|
||||||
const std::string kNameOfTrack("somename");
|
|
||||||
// The number of bytes must be larger than 0xFFFFFFFF for this test.
|
// The number of bytes must be larger than 0xFFFFFFFF for this test.
|
||||||
const int64 kBytesSent = 12345678901234LL;
|
const int64 kBytesSent = 12345678901234LL;
|
||||||
const std::string kBytesSentString("12345678901234");
|
const std::string kBytesSentString("12345678901234");
|
||||||
|
|
||||||
stats.set_session(&session_);
|
stats.set_session(&session_);
|
||||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
AddVideoTrackStats();
|
||||||
webrtc::MediaStream::Create("streamlabel"));
|
stats.AddStream(stream_);
|
||||||
stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
|
|
||||||
stats.AddStream(stream);
|
|
||||||
|
|
||||||
// Construct a stats value to read.
|
// Construct a stats value to read.
|
||||||
video_sender_info.ssrcs.push_back(1234);
|
video_sender_info.ssrcs.push_back(1234);
|
||||||
@ -319,9 +350,6 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
|
|||||||
EXPECT_CALL(*media_channel, GetStats(_))
|
EXPECT_CALL(*media_channel, GetStats(_))
|
||||||
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
||||||
Return(true)));
|
Return(true)));
|
||||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
|
|
||||||
Return(true)));
|
|
||||||
stats.UpdateStats();
|
stats.UpdateStats();
|
||||||
stats.GetStats(NULL, &reports);
|
stats.GetStats(NULL, &reports);
|
||||||
std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
|
std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
|
||||||
@ -339,16 +367,12 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
|
|||||||
cricket::VideoMediaInfo stats_read;
|
cricket::VideoMediaInfo stats_read;
|
||||||
// Set up an SSRC just to test that we get both kinds of stats back: SSRC and
|
// Set up an SSRC just to test that we get both kinds of stats back: SSRC and
|
||||||
// BWE.
|
// BWE.
|
||||||
const uint32 kSsrcOfTrack = 1234;
|
|
||||||
const std::string kNameOfTrack("somename");
|
|
||||||
const int64 kBytesSent = 12345678901234LL;
|
const int64 kBytesSent = 12345678901234LL;
|
||||||
const std::string kBytesSentString("12345678901234");
|
const std::string kBytesSentString("12345678901234");
|
||||||
|
|
||||||
stats.set_session(&session_);
|
stats.set_session(&session_);
|
||||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
AddVideoTrackStats();
|
||||||
webrtc::MediaStream::Create("streamlabel"));
|
stats.AddStream(stream_);
|
||||||
stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
|
|
||||||
stats.AddStream(stream);
|
|
||||||
|
|
||||||
// Construct a stats value to read.
|
// Construct a stats value to read.
|
||||||
video_sender_info.ssrcs.push_back(1234);
|
video_sender_info.ssrcs.push_back(1234);
|
||||||
@ -365,9 +389,7 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
|
|||||||
EXPECT_CALL(*media_channel, GetStats(_))
|
EXPECT_CALL(*media_channel, GetStats(_))
|
||||||
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
||||||
Return(true)));
|
Return(true)));
|
||||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
|
|
||||||
Return(true)));
|
|
||||||
stats.UpdateStats();
|
stats.UpdateStats();
|
||||||
stats.GetStats(NULL, &reports);
|
stats.GetStats(NULL, &reports);
|
||||||
std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
|
std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
|
||||||
@ -417,13 +439,8 @@ TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
|
|||||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
||||||
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||||
media_engine_, media_channel, &session_, "", false, NULL);
|
media_engine_, media_channel, &session_, "", false, NULL);
|
||||||
const std::string kTrackId("somename");
|
AddVideoTrackStats();
|
||||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
stats.AddStream(stream_);
|
||||||
webrtc::MediaStream::Create("streamlabel"));
|
|
||||||
talk_base::scoped_refptr<webrtc::VideoTrack> track =
|
|
||||||
webrtc::VideoTrack::Create(kTrackId, NULL);
|
|
||||||
stream->AddTrack(track);
|
|
||||||
stats.AddStream(stream);
|
|
||||||
|
|
||||||
stats.set_session(&session_);
|
stats.set_session(&session_);
|
||||||
|
|
||||||
@ -449,13 +466,8 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
|||||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
||||||
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||||
media_engine_, media_channel, &session_, "", false, NULL);
|
media_engine_, media_channel, &session_, "", false, NULL);
|
||||||
const std::string kTrackId("somename");
|
AddVideoTrackStats();
|
||||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
stats.AddStream(stream_);
|
||||||
webrtc::MediaStream::Create("streamlabel"));
|
|
||||||
talk_base::scoped_refptr<webrtc::VideoTrack> track =
|
|
||||||
webrtc::VideoTrack::Create(kTrackId, NULL);
|
|
||||||
stream->AddTrack(track);
|
|
||||||
stats.AddStream(stream);
|
|
||||||
|
|
||||||
stats.set_session(&session_);
|
stats.set_session(&session_);
|
||||||
|
|
||||||
@ -464,7 +476,6 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
|||||||
// Constructs an ssrc stats update.
|
// Constructs an ssrc stats update.
|
||||||
cricket::VideoSenderInfo video_sender_info;
|
cricket::VideoSenderInfo video_sender_info;
|
||||||
cricket::VideoMediaInfo stats_read;
|
cricket::VideoMediaInfo stats_read;
|
||||||
const uint32 kSsrcOfTrack = 1234;
|
|
||||||
const int64 kBytesSent = 12345678901234LL;
|
const int64 kBytesSent = 12345678901234LL;
|
||||||
|
|
||||||
// Construct a stats value to read.
|
// Construct a stats value to read.
|
||||||
@ -477,23 +488,20 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
|||||||
EXPECT_CALL(*media_channel, GetStats(_))
|
EXPECT_CALL(*media_channel, GetStats(_))
|
||||||
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
||||||
Return(true)));
|
Return(true)));
|
||||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kTrackId),
|
|
||||||
Return(true)));
|
|
||||||
|
|
||||||
stats.UpdateStats();
|
stats.UpdateStats();
|
||||||
stats.GetStats(NULL, &reports);
|
stats.GetStats(NULL, &reports);
|
||||||
// |reports| should contain one session report, one track report, and one ssrc
|
// |reports| should contain at least one session report, one track report,
|
||||||
// report.
|
// and one ssrc report.
|
||||||
EXPECT_EQ((size_t)3, reports.size());
|
EXPECT_LE((size_t)3, reports.size());
|
||||||
const webrtc::StatsReport* track_report = FindNthReportByType(
|
const webrtc::StatsReport* track_report = FindNthReportByType(
|
||||||
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
|
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
|
||||||
EXPECT_FALSE(track_report == NULL);
|
EXPECT_FALSE(track_report == NULL);
|
||||||
|
|
||||||
stats.GetStats(track, &reports);
|
stats.GetStats(track_, &reports);
|
||||||
// |reports| should contain one session report, one track report, and one ssrc
|
// |reports| should contain at least one session report, one track report,
|
||||||
// report.
|
// and one ssrc report.
|
||||||
EXPECT_EQ((size_t)3, reports.size());
|
EXPECT_LE((size_t)3, reports.size());
|
||||||
track_report = FindNthReportByType(
|
track_report = FindNthReportByType(
|
||||||
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
|
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
|
||||||
EXPECT_FALSE(track_report == NULL);
|
EXPECT_FALSE(track_report == NULL);
|
||||||
@ -516,13 +524,8 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
|||||||
const std::string kVcName("vcname");
|
const std::string kVcName("vcname");
|
||||||
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||||
media_engine_, media_channel, &session_, kVcName, false, NULL);
|
media_engine_, media_channel, &session_, kVcName, false, NULL);
|
||||||
const std::string kTrackId("somename");
|
AddVideoTrackStats();
|
||||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
stats.AddStream(stream_);
|
||||||
webrtc::MediaStream::Create("streamlabel"));
|
|
||||||
talk_base::scoped_refptr<webrtc::VideoTrack> track =
|
|
||||||
webrtc::VideoTrack::Create(kTrackId, NULL);
|
|
||||||
stream->AddTrack(track);
|
|
||||||
stats.AddStream(stream);
|
|
||||||
|
|
||||||
stats.set_session(&session_);
|
stats.set_session(&session_);
|
||||||
|
|
||||||
@ -531,7 +534,6 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
|||||||
// Constructs an ssrc stats update.
|
// Constructs an ssrc stats update.
|
||||||
cricket::VideoSenderInfo video_sender_info;
|
cricket::VideoSenderInfo video_sender_info;
|
||||||
cricket::VideoMediaInfo stats_read;
|
cricket::VideoMediaInfo stats_read;
|
||||||
const uint32 kSsrcOfTrack = 1234;
|
|
||||||
const int64 kBytesSent = 12345678901234LL;
|
const int64 kBytesSent = 12345678901234LL;
|
||||||
|
|
||||||
// Construct a stats value to read.
|
// Construct a stats value to read.
|
||||||
@ -544,23 +546,10 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
|||||||
EXPECT_CALL(*media_channel, GetStats(_))
|
EXPECT_CALL(*media_channel, GetStats(_))
|
||||||
.WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
|
.WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
|
||||||
Return(true)));
|
Return(true)));
|
||||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kTrackId),
|
|
||||||
Return(true)));
|
|
||||||
|
|
||||||
// Instruct the session to return stats containing the transport channel.
|
InitSessionStats(kVcName);
|
||||||
const std::string kTransportName("trspname");
|
|
||||||
cricket::SessionStats session_stats;
|
|
||||||
cricket::TransportStats transport_stats;
|
|
||||||
cricket::TransportChannelStats channel_stats;
|
|
||||||
channel_stats.component = 1;
|
|
||||||
transport_stats.content_name = kTransportName;
|
|
||||||
transport_stats.channel_stats.push_back(channel_stats);
|
|
||||||
|
|
||||||
session_stats.transport_stats[kTransportName] = transport_stats;
|
|
||||||
session_stats.proxy_to_transport[kVcName] = kTransportName;
|
|
||||||
EXPECT_CALL(session_, GetStats(_))
|
EXPECT_CALL(session_, GetStats(_))
|
||||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats),
|
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||||
Return(true)));
|
Return(true)));
|
||||||
|
|
||||||
stats.UpdateStats();
|
stats.UpdateStats();
|
||||||
@ -575,6 +564,78 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
|||||||
ASSERT_FALSE(transport_report == NULL);
|
ASSERT_FALSE(transport_report == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that a remote stats object will not be created for
|
||||||
|
// an outgoing SSRC where remote stats are not returned.
|
||||||
|
TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
|
||||||
|
webrtc::StatsCollector stats; // Implementation under test.
|
||||||
|
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
||||||
|
// The content_name known by the video channel.
|
||||||
|
const std::string kVcName("vcname");
|
||||||
|
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||||
|
media_engine_, media_channel, &session_, kVcName, false, NULL);
|
||||||
|
AddVideoTrackStats();
|
||||||
|
stats.AddStream(stream_);
|
||||||
|
|
||||||
|
stats.set_session(&session_);
|
||||||
|
|
||||||
|
EXPECT_CALL(session_, video_channel())
|
||||||
|
.WillRepeatedly(ReturnNull());
|
||||||
|
|
||||||
|
stats.UpdateStats();
|
||||||
|
webrtc::StatsReports reports;
|
||||||
|
stats.GetStats(NULL, &reports);
|
||||||
|
const webrtc::StatsReport* remote_report = FindNthReportByType(reports,
|
||||||
|
webrtc::StatsReport::kStatsReportTypeRemoteSsrc, 1);
|
||||||
|
EXPECT_TRUE(remote_report == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test verifies that a remote stats object will be created for
|
||||||
|
// an outgoing SSRC where stats are returned.
|
||||||
|
TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
|
||||||
|
webrtc::StatsCollector stats; // Implementation under test.
|
||||||
|
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
||||||
|
// The content_name known by the video channel.
|
||||||
|
const std::string kVcName("vcname");
|
||||||
|
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||||
|
media_engine_, media_channel, &session_, kVcName, false, NULL);
|
||||||
|
AddVideoTrackStats();
|
||||||
|
stats.AddStream(stream_);
|
||||||
|
|
||||||
|
stats.set_session(&session_);
|
||||||
|
|
||||||
|
webrtc::StatsReports reports;
|
||||||
|
|
||||||
|
// Instruct the session to return stats containing the transport channel.
|
||||||
|
InitSessionStats(kVcName);
|
||||||
|
EXPECT_CALL(session_, GetStats(_))
|
||||||
|
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||||
|
Return(true)));
|
||||||
|
|
||||||
|
// Constructs an ssrc stats update.
|
||||||
|
cricket::VideoMediaInfo stats_read;
|
||||||
|
|
||||||
|
cricket::SsrcReceiverInfo remote_ssrc_stats;
|
||||||
|
remote_ssrc_stats.timestamp = 12345.678;
|
||||||
|
remote_ssrc_stats.ssrc = kSsrcOfTrack;
|
||||||
|
cricket::VideoSenderInfo video_sender_info;
|
||||||
|
video_sender_info.ssrcs.push_back(kSsrcOfTrack);
|
||||||
|
video_sender_info.remote_stats.push_back(remote_ssrc_stats);
|
||||||
|
stats_read.senders.push_back(video_sender_info);
|
||||||
|
|
||||||
|
EXPECT_CALL(session_, video_channel())
|
||||||
|
.WillRepeatedly(Return(&video_channel));
|
||||||
|
EXPECT_CALL(*media_channel, GetStats(_))
|
||||||
|
.WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
|
||||||
|
Return(true)));
|
||||||
|
|
||||||
|
stats.UpdateStats();
|
||||||
|
stats.GetStats(NULL, &reports);
|
||||||
|
const webrtc::StatsReport* remote_report = FindNthReportByType(reports,
|
||||||
|
webrtc::StatsReport::kStatsReportTypeRemoteSsrc, 1);
|
||||||
|
EXPECT_FALSE(remote_report == NULL);
|
||||||
|
EXPECT_NE(0, remote_report->timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
// This test verifies that all chained certificates are correctly
|
// This test verifies that all chained certificates are correctly
|
||||||
// reported
|
// reported
|
||||||
TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
|
TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
|
||||||
@ -638,6 +699,7 @@ TEST_F(StatsCollectorTest, NoTransport) {
|
|||||||
EXPECT_CALL(session_, GetStats(_))
|
EXPECT_CALL(session_, GetStats(_))
|
||||||
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
||||||
Return(true)));
|
Return(true)));
|
||||||
|
|
||||||
EXPECT_CALL(session_, video_channel())
|
EXPECT_CALL(session_, video_channel())
|
||||||
.WillRepeatedly(ReturnNull());
|
.WillRepeatedly(ReturnNull());
|
||||||
|
|
||||||
@ -712,5 +774,4 @@ TEST_F(StatsCollectorTest, NoCertificates) {
|
|||||||
ASSERT_EQ(kNotFound, remote_certificate_id);
|
ASSERT_EQ(kNotFound, remote_certificate_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -88,6 +88,10 @@ class StatsReport {
|
|||||||
// The |id| field is the SSRC in decimal form of the rtp stream.
|
// The |id| field is the SSRC in decimal form of the rtp stream.
|
||||||
static const char kStatsReportTypeSsrc[];
|
static const char kStatsReportTypeSsrc[];
|
||||||
|
|
||||||
|
// StatsReport of |type| = "remoteSsrc" is statistics for a specific
|
||||||
|
// rtp stream, generated by the remote end of the connection.
|
||||||
|
static const char kStatsReportTypeRemoteSsrc[];
|
||||||
|
|
||||||
// StatsReport of |type| = "googTrack" is statistics for a specific media
|
// StatsReport of |type| = "googTrack" is statistics for a specific media
|
||||||
// track. The |id| field is the track id.
|
// track. The |id| field is the track id.
|
||||||
static const char kStatsReportTypeTrack[];
|
static const char kStatsReportTypeTrack[];
|
||||||
@ -137,6 +141,13 @@ class StatsReport {
|
|||||||
static const char kStatsValueNameFrameRateReceived[];
|
static const char kStatsValueNameFrameRateReceived[];
|
||||||
static const char kStatsValueNameFrameRateDecoded[];
|
static const char kStatsValueNameFrameRateDecoded[];
|
||||||
static const char kStatsValueNameFrameRateOutput[];
|
static const char kStatsValueNameFrameRateOutput[];
|
||||||
|
static const char kStatsValueNameDecodeMs[];
|
||||||
|
static const char kStatsValueNameMaxDecodeMs[];
|
||||||
|
static const char kStatsValueNameCurrentDelayMs[];
|
||||||
|
static const char kStatsValueNameTargetDelayMs[];
|
||||||
|
static const char kStatsValueNameJitterBufferMs[];
|
||||||
|
static const char kStatsValueNameMinPlayoutDelayMs[];
|
||||||
|
static const char kStatsValueNameRenderDelayMs[];
|
||||||
static const char kStatsValueNameFrameRateInput[];
|
static const char kStatsValueNameFrameRateInput[];
|
||||||
static const char kStatsValueNameFrameRateSent[];
|
static const char kStatsValueNameFrameRateSent[];
|
||||||
static const char kStatsValueNameFrameWidthReceived[];
|
static const char kStatsValueNameFrameWidthReceived[];
|
||||||
|
@ -119,7 +119,6 @@ class FakeConstraints : public webrtc::MediaConstraintsInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetAllowDtlsSctpDataChannels() {
|
void SetAllowDtlsSctpDataChannels() {
|
||||||
SetMandatory(MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
|
||||||
SetMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true);
|
SetMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ static const char kSdpSctpDataChannelString[] =
|
|||||||
"a=ice-ufrag:ufrag_data\r\n"
|
"a=ice-ufrag:ufrag_data\r\n"
|
||||||
"a=ice-pwd:pwd_data\r\n"
|
"a=ice-pwd:pwd_data\r\n"
|
||||||
"a=mid:data_content_name\r\n"
|
"a=mid:data_content_name\r\n"
|
||||||
"a=sctpmap:5000 webrtc-datachannel 65536\r\n";
|
"a=sctpmap:5000 webrtc-datachannel 1024\r\n";
|
||||||
|
|
||||||
static const char kSdpSctpDataChannelWithCandidatesString[] =
|
static const char kSdpSctpDataChannelWithCandidatesString[] =
|
||||||
"m=application 2345 DTLS/SCTP 5000\r\n"
|
"m=application 2345 DTLS/SCTP 5000\r\n"
|
||||||
@ -297,7 +297,7 @@ static const char kSdpSctpDataChannelWithCandidatesString[] =
|
|||||||
"a=ice-ufrag:ufrag_data\r\n"
|
"a=ice-ufrag:ufrag_data\r\n"
|
||||||
"a=ice-pwd:pwd_data\r\n"
|
"a=ice-pwd:pwd_data\r\n"
|
||||||
"a=mid:data_content_name\r\n"
|
"a=mid:data_content_name\r\n"
|
||||||
"a=sctpmap:5000 webrtc-datachannel 65536\r\n";
|
"a=sctpmap:5000 webrtc-datachannel 1024\r\n";
|
||||||
|
|
||||||
|
|
||||||
// One candidate reference string as per W3c spec.
|
// One candidate reference string as per W3c spec.
|
||||||
|
@ -68,10 +68,7 @@ const char MediaConstraintsInterface::kEnableRtpDataChannels[] =
|
|||||||
// line flag. So it is prefixed with kInternalConstraintPrefix so JS values
|
// line flag. So it is prefixed with kInternalConstraintPrefix so JS values
|
||||||
// will be removed.
|
// will be removed.
|
||||||
const char MediaConstraintsInterface::kEnableSctpDataChannels[] =
|
const char MediaConstraintsInterface::kEnableSctpDataChannels[] =
|
||||||
"internalSctpDataChannels";
|
"deprecatedSctpDataChannels";
|
||||||
|
|
||||||
const char MediaConstraintsInterface::kInternalDisableEncryption[] =
|
|
||||||
"internalDisableEncryption";
|
|
||||||
|
|
||||||
// Error messages
|
// Error messages
|
||||||
const char kSetLocalSdpFailed[] = "SetLocalDescription failed: ";
|
const char kSetLocalSdpFailed[] = "SetLocalDescription failed: ";
|
||||||
@ -458,6 +455,7 @@ WebRtcSession::~WebRtcSession() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WebRtcSession::Initialize(
|
bool WebRtcSession::Initialize(
|
||||||
|
const PeerConnectionFactoryInterface::Options& options,
|
||||||
const MediaConstraintsInterface* constraints,
|
const MediaConstraintsInterface* constraints,
|
||||||
DTLSIdentityServiceInterface* dtls_identity_service) {
|
DTLSIdentityServiceInterface* dtls_identity_service) {
|
||||||
// TODO(perkj): Take |constraints| into consideration. Return false if not all
|
// TODO(perkj): Take |constraints| into consideration. Return false if not all
|
||||||
@ -476,19 +474,16 @@ bool WebRtcSession::Initialize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enable creation of RTP data channels if the kEnableRtpDataChannels is set.
|
// Enable creation of RTP data channels if the kEnableRtpDataChannels is set.
|
||||||
// It takes precendence over the kEnableSctpDataChannels constraint.
|
// It takes precendence over the disable_sctp_data_channels
|
||||||
|
// PeerConnectionFactoryInterface::Options.
|
||||||
if (FindConstraint(
|
if (FindConstraint(
|
||||||
constraints, MediaConstraintsInterface::kEnableRtpDataChannels,
|
constraints, MediaConstraintsInterface::kEnableRtpDataChannels,
|
||||||
&value, NULL) && value) {
|
&value, NULL) && value) {
|
||||||
LOG(LS_INFO) << "Allowing RTP data engine.";
|
LOG(LS_INFO) << "Allowing RTP data engine.";
|
||||||
data_channel_type_ = cricket::DCT_RTP;
|
data_channel_type_ = cricket::DCT_RTP;
|
||||||
} else {
|
} else {
|
||||||
bool sctp_enabled = FindConstraint(
|
|
||||||
constraints,
|
|
||||||
MediaConstraintsInterface::kEnableSctpDataChannels,
|
|
||||||
&value, NULL) && value;
|
|
||||||
// DTLS has to be enabled to use SCTP.
|
// DTLS has to be enabled to use SCTP.
|
||||||
if (sctp_enabled && dtls_enabled_) {
|
if (!options.disable_sctp_data_channels && dtls_enabled_) {
|
||||||
LOG(LS_INFO) << "Allowing SCTP data engine.";
|
LOG(LS_INFO) << "Allowing SCTP data engine.";
|
||||||
data_channel_type_ = cricket::DCT_SCTP;
|
data_channel_type_ = cricket::DCT_SCTP;
|
||||||
}
|
}
|
||||||
@ -520,11 +515,7 @@ bool WebRtcSession::Initialize(
|
|||||||
webrtc_session_desc_factory_->SignalIdentityReady.connect(
|
webrtc_session_desc_factory_->SignalIdentityReady.connect(
|
||||||
this, &WebRtcSession::OnIdentityReady);
|
this, &WebRtcSession::OnIdentityReady);
|
||||||
|
|
||||||
// Disable encryption if kDisableEncryption is set.
|
if (options.disable_encryption) {
|
||||||
if (FindConstraint(
|
|
||||||
constraints,
|
|
||||||
MediaConstraintsInterface::kInternalDisableEncryption,
|
|
||||||
&value, NULL) && value) {
|
|
||||||
webrtc_session_desc_factory_->set_secure(cricket::SEC_DISABLED);
|
webrtc_session_desc_factory_->set_secure(cricket::SEC_DISABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,8 @@ class WebRtcSession : public cricket::BaseSession,
|
|||||||
MediaStreamSignaling* mediastream_signaling);
|
MediaStreamSignaling* mediastream_signaling);
|
||||||
virtual ~WebRtcSession();
|
virtual ~WebRtcSession();
|
||||||
|
|
||||||
bool Initialize(const MediaConstraintsInterface* constraints,
|
bool Initialize(const PeerConnectionFactoryInterface::Options& options,
|
||||||
|
const MediaConstraintsInterface* constraints,
|
||||||
DTLSIdentityServiceInterface* dtls_identity_service);
|
DTLSIdentityServiceInterface* dtls_identity_service);
|
||||||
// Deletes the voice, video and data channel and changes the session state
|
// Deletes the voice, video and data channel and changes the session state
|
||||||
// to STATE_RECEIVEDTERMINATE.
|
// to STATE_RECEIVEDTERMINATE.
|
||||||
|
@ -81,6 +81,7 @@ using webrtc::FakeConstraints;
|
|||||||
using webrtc::IceCandidateCollection;
|
using webrtc::IceCandidateCollection;
|
||||||
using webrtc::JsepIceCandidate;
|
using webrtc::JsepIceCandidate;
|
||||||
using webrtc::JsepSessionDescription;
|
using webrtc::JsepSessionDescription;
|
||||||
|
using webrtc::PeerConnectionFactoryInterface;
|
||||||
using webrtc::PeerConnectionInterface;
|
using webrtc::PeerConnectionInterface;
|
||||||
using webrtc::SessionDescriptionInterface;
|
using webrtc::SessionDescriptionInterface;
|
||||||
using webrtc::StreamCollection;
|
using webrtc::StreamCollection;
|
||||||
@ -317,7 +318,8 @@ class WebRtcSessionTest : public testing::Test {
|
|||||||
EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
|
EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
|
||||||
observer_.ice_gathering_state_);
|
observer_.ice_gathering_state_);
|
||||||
|
|
||||||
EXPECT_TRUE(session_->Initialize(constraints_.get(), identity_service));
|
EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
|
||||||
|
identity_service));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitWithDtmfCodec() {
|
void InitWithDtmfCodec() {
|
||||||
@ -919,6 +921,7 @@ class WebRtcSessionTest : public testing::Test {
|
|||||||
cricket::TestStunServer stun_server_;
|
cricket::TestStunServer stun_server_;
|
||||||
talk_base::FakeNetworkManager network_manager_;
|
talk_base::FakeNetworkManager network_manager_;
|
||||||
cricket::BasicPortAllocator allocator_;
|
cricket::BasicPortAllocator allocator_;
|
||||||
|
PeerConnectionFactoryInterface::Options options_;
|
||||||
talk_base::scoped_ptr<FakeConstraints> constraints_;
|
talk_base::scoped_ptr<FakeConstraints> constraints_;
|
||||||
FakeMediaStreamSignaling mediastream_signaling_;
|
FakeMediaStreamSignaling mediastream_signaling_;
|
||||||
talk_base::scoped_ptr<WebRtcSessionForTest> session_;
|
talk_base::scoped_ptr<WebRtcSessionForTest> session_;
|
||||||
@ -1932,9 +1935,7 @@ TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
|
TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
|
||||||
constraints_.reset(new FakeConstraints());
|
options_.disable_encryption = true;
|
||||||
constraints_->AddOptional(
|
|
||||||
webrtc::MediaConstraintsInterface::kInternalDisableEncryption, true);
|
|
||||||
Init(NULL);
|
Init(NULL);
|
||||||
mediastream_signaling_.SendAudioVideoStream1();
|
mediastream_signaling_.SendAudioVideoStream1();
|
||||||
scoped_ptr<SessionDescriptionInterface> offer(
|
scoped_ptr<SessionDescriptionInterface> offer(
|
||||||
@ -2424,9 +2425,7 @@ TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
|
|||||||
|
|
||||||
// This test verifies the crypto parameter when security is disabled.
|
// This test verifies the crypto parameter when security is disabled.
|
||||||
TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
|
TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
|
||||||
constraints_.reset(new FakeConstraints());
|
options_.disable_encryption = true;
|
||||||
constraints_->AddOptional(
|
|
||||||
webrtc::MediaConstraintsInterface::kInternalDisableEncryption, true);
|
|
||||||
Init(NULL);
|
Init(NULL);
|
||||||
mediastream_signaling_.SendAudioVideoStream1();
|
mediastream_signaling_.SendAudioVideoStream1();
|
||||||
talk_base::scoped_ptr<SessionDescriptionInterface> offer(
|
talk_base::scoped_ptr<SessionDescriptionInterface> offer(
|
||||||
@ -2567,8 +2566,8 @@ TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
|
|||||||
constraints_.reset(new FakeConstraints());
|
constraints_.reset(new FakeConstraints());
|
||||||
constraints_->AddOptional(
|
constraints_->AddOptional(
|
||||||
webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
|
webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
|
||||||
constraints_->AddOptional(
|
options_.disable_sctp_data_channels = false;
|
||||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
|
||||||
InitWithDtls(false);
|
InitWithDtls(false);
|
||||||
|
|
||||||
SetLocalDescriptionWithDataChannel();
|
SetLocalDescriptionWithDataChannel();
|
||||||
@ -2578,9 +2577,6 @@ TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
|
|||||||
TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
|
TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
|
||||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||||
|
|
||||||
constraints_.reset(new FakeConstraints());
|
|
||||||
constraints_->AddOptional(
|
|
||||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
|
||||||
InitWithDtls(false);
|
InitWithDtls(false);
|
||||||
|
|
||||||
talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
|
talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
|
||||||
@ -2591,9 +2587,6 @@ TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
|
|||||||
TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
|
TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
|
||||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||||
SetFactoryDtlsSrtp();
|
SetFactoryDtlsSrtp();
|
||||||
constraints_.reset(new FakeConstraints());
|
|
||||||
constraints_->AddOptional(
|
|
||||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
|
||||||
InitWithDtls(false);
|
InitWithDtls(false);
|
||||||
|
|
||||||
// Create remote offer with SCTP.
|
// Create remote offer with SCTP.
|
||||||
@ -2612,8 +2605,6 @@ TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
|
|||||||
|
|
||||||
TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
|
TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
|
||||||
constraints_.reset(new FakeConstraints());
|
constraints_.reset(new FakeConstraints());
|
||||||
constraints_->AddOptional(
|
|
||||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
|
||||||
constraints_->AddOptional(
|
constraints_->AddOptional(
|
||||||
webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
|
webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
|
||||||
InitWithDtls(false);
|
InitWithDtls(false);
|
||||||
@ -2625,24 +2616,26 @@ TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
|
|||||||
TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
|
TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
|
||||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||||
|
|
||||||
constraints_.reset(new FakeConstraints());
|
|
||||||
constraints_->AddOptional(
|
|
||||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
|
||||||
InitWithDtls(false);
|
InitWithDtls(false);
|
||||||
|
|
||||||
SetLocalDescriptionWithDataChannel();
|
SetLocalDescriptionWithDataChannel();
|
||||||
EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
|
EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WebRtcSessionTest, TestDisableSctpDataChannels) {
|
||||||
|
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||||
|
options_.disable_sctp_data_channels = true;
|
||||||
|
InitWithDtls(false);
|
||||||
|
|
||||||
|
SetLocalDescriptionWithDataChannel();
|
||||||
|
EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
|
TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
|
||||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||||
const int new_send_port = 9998;
|
const int new_send_port = 9998;
|
||||||
const int new_recv_port = 7775;
|
const int new_recv_port = 7775;
|
||||||
|
|
||||||
constraints_.reset(new FakeConstraints());
|
|
||||||
constraints_->AddOptional(
|
|
||||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
|
||||||
|
|
||||||
InitWithDtls(false);
|
InitWithDtls(false);
|
||||||
SetFactoryDtlsSrtp();
|
SetFactoryDtlsSrtp();
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class FixedSizeLockFreeQueue {
|
|||||||
FixedSizeLockFreeQueue() : pushed_count_(0),
|
FixedSizeLockFreeQueue() : pushed_count_(0),
|
||||||
popped_count_(0),
|
popped_count_(0),
|
||||||
capacity_(0),
|
capacity_(0),
|
||||||
data_(NULL) {}
|
data_() {}
|
||||||
// Constructs an empty queue with the given capacity.
|
// Constructs an empty queue with the given capacity.
|
||||||
FixedSizeLockFreeQueue(size_t capacity) : pushed_count_(0),
|
FixedSizeLockFreeQueue(size_t capacity) : pushed_count_(0),
|
||||||
popped_count_(0),
|
popped_count_(0),
|
||||||
@ -157,7 +157,7 @@ class FixedSizeLockFreeQueue {
|
|||||||
volatile Atomic32 pushed_count_;
|
volatile Atomic32 pushed_count_;
|
||||||
volatile Atomic32 popped_count_;
|
volatile Atomic32 popped_count_;
|
||||||
size_t capacity_;
|
size_t capacity_;
|
||||||
talk_base::scoped_array<T> data_;
|
talk_base::scoped_ptr<T[]> data_;
|
||||||
DISALLOW_COPY_AND_ASSIGN(FixedSizeLockFreeQueue);
|
DISALLOW_COPY_AND_ASSIGN(FixedSizeLockFreeQueue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class Buffer {
|
|||||||
}
|
}
|
||||||
void SetCapacity(size_t capacity) {
|
void SetCapacity(size_t capacity) {
|
||||||
if (capacity > capacity_) {
|
if (capacity > capacity_) {
|
||||||
talk_base::scoped_array<char> data(new char[capacity]);
|
talk_base::scoped_ptr<char[]> data(new char[capacity]);
|
||||||
memcpy(data.get(), data_.get(), length_);
|
memcpy(data.get(), data_.get(), length_);
|
||||||
data_.swap(data);
|
data_.swap(data);
|
||||||
capacity_ = capacity;
|
capacity_ = capacity;
|
||||||
@ -109,7 +109,7 @@ class Buffer {
|
|||||||
SetData(data, length);
|
SetData(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_array<char> data_;
|
scoped_ptr<char[]> data_;
|
||||||
size_t length_;
|
size_t length_;
|
||||||
size_t capacity_;
|
size_t capacity_;
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TALK_BASE_COMMON_H_
|
#ifndef TALK_BASE_COMMON_H_ // NOLINT
|
||||||
#define TALK_BASE_COMMON_H_
|
#define TALK_BASE_COMMON_H_
|
||||||
|
|
||||||
#include "talk/base/basictypes.h"
|
#include "talk/base/basictypes.h"
|
||||||
@ -64,7 +64,7 @@ inline void Unused(const void*) {}
|
|||||||
#define strnicmp(x, y, n) strncasecmp(x, y, n)
|
#define strnicmp(x, y, n) strncasecmp(x, y, n)
|
||||||
#define stricmp(x, y) strcasecmp(x, y)
|
#define stricmp(x, y) strcasecmp(x, y)
|
||||||
|
|
||||||
// TODO: Remove this. std::max should be used everywhere in the code.
|
// TODO(fbarchard): Remove this. std::max should be used everywhere in the code.
|
||||||
// NOMINMAX must be defined where we include <windows.h>.
|
// NOMINMAX must be defined where we include <windows.h>.
|
||||||
#define stdmax(x, y) std::max(x, y)
|
#define stdmax(x, y) std::max(x, y)
|
||||||
#else
|
#else
|
||||||
@ -181,9 +181,28 @@ inline bool ImplicitCastToBool(bool result) { return result; }
|
|||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#define OVERRIDE override
|
#define OVERRIDE override
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
|
// Clang defaults to C++03 and warns about using override. Squelch that.
|
||||||
|
// Intentionally no push/pop here so all users of OVERRIDE ignore the warning
|
||||||
|
// too. This is like passing -Wno-c++11-extensions, except that GCC won't die
|
||||||
|
// (because it won't see this pragma).
|
||||||
|
#pragma clang diagnostic ignored "-Wc++11-extensions"
|
||||||
#define OVERRIDE override
|
#define OVERRIDE override
|
||||||
#else
|
#else
|
||||||
#define OVERRIDE
|
#define OVERRIDE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // TALK_BASE_COMMON_H_
|
// Annotate a function indicating the caller must examine the return value.
|
||||||
|
// Use like:
|
||||||
|
// int foo() WARN_UNUSED_RESULT;
|
||||||
|
// To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>.
|
||||||
|
// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and
|
||||||
|
// libjingle are merged.
|
||||||
|
#if !defined(WARN_UNUSED_RESULT)
|
||||||
|
#if defined(COMPILER_GCC)
|
||||||
|
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||||
|
#else
|
||||||
|
#define WARN_UNUSED_RESULT
|
||||||
|
#endif
|
||||||
|
#endif // WARN_UNUSED_RESULT
|
||||||
|
|
||||||
|
#endif // TALK_BASE_COMMON_H_ // NOLINT
|
||||||
|
99
talk/base/compile_assert.h
Normal file
99
talk/base/compile_assert.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* libjingle
|
||||||
|
* Copyright 2013, Google 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// COMPILE_ASSERT macro, borrowed from google3/base/macros.h.
|
||||||
|
#ifndef TALK_BASE_COMPILE_ASSERT_H_
|
||||||
|
#define TALK_BASE_COMPILE_ASSERT_H_
|
||||||
|
|
||||||
|
// The COMPILE_ASSERT macro can be used to verify that a compile time
|
||||||
|
// expression is true. For example, you could use it to verify the
|
||||||
|
// size of a static array:
|
||||||
|
//
|
||||||
|
// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
|
||||||
|
// content_type_names_incorrect_size);
|
||||||
|
//
|
||||||
|
// or to make sure a struct is smaller than a certain size:
|
||||||
|
//
|
||||||
|
// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
|
||||||
|
//
|
||||||
|
// The second argument to the macro is the name of the variable. If
|
||||||
|
// the expression is false, most compilers will issue a warning/error
|
||||||
|
// containing the name of the variable.
|
||||||
|
|
||||||
|
// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and
|
||||||
|
// libjingle are merged.
|
||||||
|
#if !defined(COMPILE_ASSERT)
|
||||||
|
template <bool>
|
||||||
|
struct CompileAssert {
|
||||||
|
};
|
||||||
|
|
||||||
|
#define COMPILE_ASSERT(expr, msg) \
|
||||||
|
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] // NOLINT
|
||||||
|
#endif // COMPILE_ASSERT
|
||||||
|
|
||||||
|
// Implementation details of COMPILE_ASSERT:
|
||||||
|
//
|
||||||
|
// - COMPILE_ASSERT works by defining an array type that has -1
|
||||||
|
// elements (and thus is invalid) when the expression is false.
|
||||||
|
//
|
||||||
|
// - The simpler definition
|
||||||
|
//
|
||||||
|
// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
|
||||||
|
//
|
||||||
|
// does not work, as gcc supports variable-length arrays whose sizes
|
||||||
|
// are determined at run-time (this is gcc's extension and not part
|
||||||
|
// of the C++ standard). As a result, gcc fails to reject the
|
||||||
|
// following code with the simple definition:
|
||||||
|
//
|
||||||
|
// int foo;
|
||||||
|
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
|
||||||
|
// // not a compile-time constant.
|
||||||
|
//
|
||||||
|
// - By using the type CompileAssert<(bool(expr))>, we ensures that
|
||||||
|
// expr is a compile-time constant. (Template arguments must be
|
||||||
|
// determined at compile-time.)
|
||||||
|
//
|
||||||
|
// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
|
||||||
|
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
|
||||||
|
//
|
||||||
|
// CompileAssert<bool(expr)>
|
||||||
|
//
|
||||||
|
// instead, these compilers will refuse to compile
|
||||||
|
//
|
||||||
|
// COMPILE_ASSERT(5 > 0, some_message);
|
||||||
|
//
|
||||||
|
// (They seem to think the ">" in "5 > 0" marks the end of the
|
||||||
|
// template argument list.)
|
||||||
|
//
|
||||||
|
// - The array size is (bool(expr) ? 1 : -1), instead of simply
|
||||||
|
//
|
||||||
|
// ((expr) ? 1 : -1).
|
||||||
|
//
|
||||||
|
// This is to avoid running into a bug in MS VC 7.1, which
|
||||||
|
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
|
||||||
|
|
||||||
|
#endif // TALK_BASE_COMPILE_ASSERT_H_
|
@ -32,7 +32,10 @@
|
|||||||
void operator=(const TypeName&)
|
void operator=(const TypeName&)
|
||||||
|
|
||||||
// A macro to disallow the evil copy constructor and operator= functions
|
// A macro to disallow the evil copy constructor and operator= functions
|
||||||
// This should be used in the private: declarations for a class
|
// This should be used in the private: declarations for a class.
|
||||||
|
// Undefine this, just in case. Some third-party includes have their own
|
||||||
|
// version.
|
||||||
|
#undef DISALLOW_COPY_AND_ASSIGN
|
||||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||||
TypeName(const TypeName&); \
|
TypeName(const TypeName&); \
|
||||||
DISALLOW_ASSIGN(TypeName)
|
DISALLOW_ASSIGN(TypeName)
|
||||||
|
@ -210,7 +210,7 @@ float CpuSampler::GetSystemLoad() {
|
|||||||
} else {
|
} else {
|
||||||
if (nt_query_system_information) {
|
if (nt_query_system_information) {
|
||||||
ULONG returned_length = 0;
|
ULONG returned_length = 0;
|
||||||
scoped_array<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> processor_info(
|
scoped_ptr<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[]> processor_info(
|
||||||
new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[cpus_]);
|
new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[cpus_]);
|
||||||
nt_query_system_information(
|
nt_query_system_information(
|
||||||
::SystemProcessorPerformanceInformation,
|
::SystemProcessorPerformanceInformation,
|
||||||
@ -281,6 +281,13 @@ float CpuSampler::GetSystemLoad() {
|
|||||||
const uint64 cpu_times = nice + system + user;
|
const uint64 cpu_times = nice + system + user;
|
||||||
const uint64 total_times = cpu_times + idle;
|
const uint64 total_times = cpu_times + idle;
|
||||||
#endif // defined(LINUX) || defined(ANDROID)
|
#endif // defined(LINUX) || defined(ANDROID)
|
||||||
|
|
||||||
|
#if defined(__native_client__)
|
||||||
|
// TODO(ryanpetrie): Implement this via PPAPI when it's available.
|
||||||
|
const uint64 cpu_times = 0;
|
||||||
|
const uint64 total_times = 0;
|
||||||
|
#endif // defined(__native_client__)
|
||||||
|
|
||||||
system_.prev_load_time_ = timenow;
|
system_.prev_load_time_ = timenow;
|
||||||
system_.prev_load_ = UpdateCpuLoad(total_times,
|
system_.prev_load_ = UpdateCpuLoad(total_times,
|
||||||
cpu_times * cpus_,
|
cpu_times * cpus_,
|
||||||
@ -359,6 +366,12 @@ float CpuSampler::GetProcessLoad() {
|
|||||||
(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * kNumMicrosecsPerSec +
|
(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * kNumMicrosecsPerSec +
|
||||||
usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
|
usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
|
||||||
#endif // defined(LINUX) || defined(ANDROID)
|
#endif // defined(LINUX) || defined(ANDROID)
|
||||||
|
|
||||||
|
#if defined(__native_client__)
|
||||||
|
// TODO(ryanpetrie): Implement this via PPAPI when it's available.
|
||||||
|
const uint64 cpu_times = 0;
|
||||||
|
#endif // defined(__native_client__)
|
||||||
|
|
||||||
process_.prev_load_time_ = timenow;
|
process_.prev_load_time_ = timenow;
|
||||||
process_.prev_load_ = UpdateCpuLoad(total_times,
|
process_.prev_load_ = UpdateCpuLoad(total_times,
|
||||||
cpu_times,
|
cpu_times,
|
||||||
|
@ -239,7 +239,7 @@ bool CreateRandomString(size_t len,
|
|||||||
const char* table, int table_size,
|
const char* table, int table_size,
|
||||||
std::string* str) {
|
std::string* str) {
|
||||||
str->clear();
|
str->clear();
|
||||||
scoped_array<uint8> bytes(new uint8[len]);
|
scoped_ptr<uint8[]> bytes(new uint8[len]);
|
||||||
if (!Rng().Generate(bytes.get(), len)) {
|
if (!Rng().Generate(bytes.get(), len)) {
|
||||||
LOG(LS_ERROR) << "Failed to generate random string!";
|
LOG(LS_ERROR) << "Failed to generate random string!";
|
||||||
return false;
|
return false;
|
||||||
|
@ -43,7 +43,7 @@ bool ToUtf8(const CFStringRef str16, std::string* str8) {
|
|||||||
size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
|
size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
|
||||||
kCFStringEncodingUTF8)
|
kCFStringEncodingUTF8)
|
||||||
+ 1;
|
+ 1;
|
||||||
scoped_array<char> buffer(new char[maxlen]);
|
scoped_ptr<char[]> buffer(new char[maxlen]);
|
||||||
if (!buffer || !CFStringGetCString(str16, buffer.get(), maxlen,
|
if (!buffer || !CFStringGetCString(str16, buffer.get(), maxlen,
|
||||||
kCFStringEncodingUTF8))
|
kCFStringEncodingUTF8))
|
||||||
return false;
|
return false;
|
||||||
|
@ -85,7 +85,7 @@ size_t ComputeDigest(const std::string& alg, const void* input, size_t in_len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string ComputeDigest(MessageDigest* digest, const std::string& input) {
|
std::string ComputeDigest(MessageDigest* digest, const std::string& input) {
|
||||||
scoped_array<char> output(new char[digest->Size()]);
|
scoped_ptr<char[]> output(new char[digest->Size()]);
|
||||||
ComputeDigest(digest, input.data(), input.size(),
|
ComputeDigest(digest, input.data(), input.size(),
|
||||||
output.get(), digest->Size());
|
output.get(), digest->Size());
|
||||||
return hex_encode(output.get(), digest->Size());
|
return hex_encode(output.get(), digest->Size());
|
||||||
@ -120,7 +120,7 @@ size_t ComputeHmac(MessageDigest* digest,
|
|||||||
}
|
}
|
||||||
// Copy the key to a block-sized buffer to simplify padding.
|
// Copy the key to a block-sized buffer to simplify padding.
|
||||||
// If the key is longer than a block, hash it and use the result instead.
|
// If the key is longer than a block, hash it and use the result instead.
|
||||||
scoped_array<uint8> new_key(new uint8[block_len]);
|
scoped_ptr<uint8[]> new_key(new uint8[block_len]);
|
||||||
if (key_len > block_len) {
|
if (key_len > block_len) {
|
||||||
ComputeDigest(digest, key, key_len, new_key.get(), block_len);
|
ComputeDigest(digest, key, key_len, new_key.get(), block_len);
|
||||||
memset(new_key.get() + digest->Size(), 0, block_len - digest->Size());
|
memset(new_key.get() + digest->Size(), 0, block_len - digest->Size());
|
||||||
@ -129,13 +129,13 @@ size_t ComputeHmac(MessageDigest* digest,
|
|||||||
memset(new_key.get() + key_len, 0, block_len - key_len);
|
memset(new_key.get() + key_len, 0, block_len - key_len);
|
||||||
}
|
}
|
||||||
// Set up the padding from the key, salting appropriately for each padding.
|
// Set up the padding from the key, salting appropriately for each padding.
|
||||||
scoped_array<uint8> o_pad(new uint8[block_len]), i_pad(new uint8[block_len]);
|
scoped_ptr<uint8[]> o_pad(new uint8[block_len]), i_pad(new uint8[block_len]);
|
||||||
for (size_t i = 0; i < block_len; ++i) {
|
for (size_t i = 0; i < block_len; ++i) {
|
||||||
o_pad[i] = 0x5c ^ new_key[i];
|
o_pad[i] = 0x5c ^ new_key[i];
|
||||||
i_pad[i] = 0x36 ^ new_key[i];
|
i_pad[i] = 0x36 ^ new_key[i];
|
||||||
}
|
}
|
||||||
// Inner hash; hash the inner padding, and then the input buffer.
|
// Inner hash; hash the inner padding, and then the input buffer.
|
||||||
scoped_array<uint8> inner(new uint8[digest->Size()]);
|
scoped_ptr<uint8[]> inner(new uint8[digest->Size()]);
|
||||||
digest->Update(i_pad.get(), block_len);
|
digest->Update(i_pad.get(), block_len);
|
||||||
digest->Update(input, in_len);
|
digest->Update(input, in_len);
|
||||||
digest->Finish(inner.get(), digest->Size());
|
digest->Finish(inner.get(), digest->Size());
|
||||||
@ -158,7 +158,7 @@ size_t ComputeHmac(const std::string& alg, const void* key, size_t key_len,
|
|||||||
|
|
||||||
std::string ComputeHmac(MessageDigest* digest, const std::string& key,
|
std::string ComputeHmac(MessageDigest* digest, const std::string& key,
|
||||||
const std::string& input) {
|
const std::string& input) {
|
||||||
scoped_array<char> output(new char[digest->Size()]);
|
scoped_ptr<char[]> output(new char[digest->Size()]);
|
||||||
ComputeHmac(digest, key.data(), key.size(),
|
ComputeHmac(digest, key.data(), key.size(),
|
||||||
input.data(), input.size(), output.get(), digest->Size());
|
input.data(), input.size(), output.get(), digest->Size());
|
||||||
return hex_encode(output.get(), digest->Size());
|
return hex_encode(output.get(), digest->Size());
|
||||||
|
207
talk/base/move.h
Normal file
207
talk/base/move.h
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_
|
||||||
|
#define THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_
|
||||||
|
|
||||||
|
// Macro with the boilerplate that makes a type move-only in C++03.
|
||||||
|
//
|
||||||
|
// USAGE
|
||||||
|
//
|
||||||
|
// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create
|
||||||
|
// a "move-only" type. Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be
|
||||||
|
// the first line in a class declaration.
|
||||||
|
//
|
||||||
|
// A class using this macro must call .Pass() (or somehow be an r-value already)
|
||||||
|
// before it can be:
|
||||||
|
//
|
||||||
|
// * Passed as a function argument
|
||||||
|
// * Used as the right-hand side of an assignment
|
||||||
|
// * Returned from a function
|
||||||
|
//
|
||||||
|
// Each class will still need to define their own "move constructor" and "move
|
||||||
|
// operator=" to make this useful. Here's an example of the macro, the move
|
||||||
|
// constructor, and the move operator= from the scoped_ptr class:
|
||||||
|
//
|
||||||
|
// template <typename T>
|
||||||
|
// class scoped_ptr {
|
||||||
|
// MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
|
||||||
|
// public:
|
||||||
|
// scoped_ptr(RValue& other) : ptr_(other.release()) { }
|
||||||
|
// scoped_ptr& operator=(RValue& other) {
|
||||||
|
// swap(other);
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// Note that the constructor must NOT be marked explicit.
|
||||||
|
//
|
||||||
|
// For consistency, the second parameter to the macro should always be RValue
|
||||||
|
// unless you have a strong reason to do otherwise. It is only exposed as a
|
||||||
|
// macro parameter so that the move constructor and move operator= don't look
|
||||||
|
// like they're using a phantom type.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// HOW THIS WORKS
|
||||||
|
//
|
||||||
|
// For a thorough explanation of this technique, see:
|
||||||
|
//
|
||||||
|
// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor
|
||||||
|
//
|
||||||
|
// The summary is that we take advantage of 2 properties:
|
||||||
|
//
|
||||||
|
// 1) non-const references will not bind to r-values.
|
||||||
|
// 2) C++ can apply one user-defined conversion when initializing a
|
||||||
|
// variable.
|
||||||
|
//
|
||||||
|
// The first lets us disable the copy constructor and assignment operator
|
||||||
|
// by declaring private version of them with a non-const reference parameter.
|
||||||
|
//
|
||||||
|
// For l-values, direct initialization still fails like in
|
||||||
|
// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment
|
||||||
|
// operators are private.
|
||||||
|
//
|
||||||
|
// For r-values, the situation is different. The copy constructor and
|
||||||
|
// assignment operator are not viable due to (1), so we are trying to call
|
||||||
|
// a non-existent constructor and non-existing operator= rather than a private
|
||||||
|
// one. Since we have not committed an error quite yet, we can provide an
|
||||||
|
// alternate conversion sequence and a constructor. We add
|
||||||
|
//
|
||||||
|
// * a private struct named "RValue"
|
||||||
|
// * a user-defined conversion "operator RValue()"
|
||||||
|
// * a "move constructor" and "move operator=" that take the RValue& as
|
||||||
|
// their sole parameter.
|
||||||
|
//
|
||||||
|
// Only r-values will trigger this sequence and execute our "move constructor"
|
||||||
|
// or "move operator=." L-values will match the private copy constructor and
|
||||||
|
// operator= first giving a "private in this context" error. This combination
|
||||||
|
// gives us a move-only type.
|
||||||
|
//
|
||||||
|
// For signaling a destructive transfer of data from an l-value, we provide a
|
||||||
|
// method named Pass() which creates an r-value for the current instance
|
||||||
|
// triggering the move constructor or move operator=.
|
||||||
|
//
|
||||||
|
// Other ways to get r-values is to use the result of an expression like a
|
||||||
|
// function call.
|
||||||
|
//
|
||||||
|
// Here's an example with comments explaining what gets triggered where:
|
||||||
|
//
|
||||||
|
// class Foo {
|
||||||
|
// MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue);
|
||||||
|
//
|
||||||
|
// public:
|
||||||
|
// ... API ...
|
||||||
|
// Foo(RValue other); // Move constructor.
|
||||||
|
// Foo& operator=(RValue rhs); // Move operator=
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// Foo MakeFoo(); // Function that returns a Foo.
|
||||||
|
//
|
||||||
|
// Foo f;
|
||||||
|
// Foo f_copy(f); // ERROR: Foo(Foo&) is private in this context.
|
||||||
|
// Foo f_assign;
|
||||||
|
// f_assign = f; // ERROR: operator=(Foo&) is private in this context.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Foo f(MakeFoo()); // R-value so alternate conversion executed.
|
||||||
|
// Foo f_copy(f.Pass()); // R-value so alternate conversion executed.
|
||||||
|
// f = f_copy.Pass(); // R-value so alternate conversion executed.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// IMPLEMENTATION SUBTLETIES WITH RValue
|
||||||
|
//
|
||||||
|
// The RValue struct is just a container for a pointer back to the original
|
||||||
|
// object. It should only ever be created as a temporary, and no external
|
||||||
|
// class should ever declare it or use it in a parameter.
|
||||||
|
//
|
||||||
|
// It is tempting to want to use the RValue type in function parameters, but
|
||||||
|
// excluding the limited usage here for the move constructor and move
|
||||||
|
// operator=, doing so would mean that the function could take both r-values
|
||||||
|
// and l-values equially which is unexpected. See COMPARED To Boost.Move for
|
||||||
|
// more details.
|
||||||
|
//
|
||||||
|
// An alternate, and incorrect, implementation of the RValue class used by
|
||||||
|
// Boost.Move makes RValue a fieldless child of the move-only type. RValue&
|
||||||
|
// is then used in place of RValue in the various operators. The RValue& is
|
||||||
|
// "created" by doing *reinterpret_cast<RValue*>(this). This has the appeal
|
||||||
|
// of never creating a temporary RValue struct even with optimizations
|
||||||
|
// disabled. Also, by virtue of inheritance you can treat the RValue
|
||||||
|
// reference as if it were the move-only type itself. Unfortunately,
|
||||||
|
// using the result of this reinterpret_cast<> is actually undefined behavior
|
||||||
|
// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer
|
||||||
|
// will generate non-working code.
|
||||||
|
//
|
||||||
|
// In optimized builds, both implementations generate the same assembly so we
|
||||||
|
// choose the one that adheres to the standard.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// COMPARED TO C++11
|
||||||
|
//
|
||||||
|
// In C++11, you would implement this functionality using an r-value reference
|
||||||
|
// and our .Pass() method would be replaced with a call to std::move().
|
||||||
|
//
|
||||||
|
// This emulation also has a deficiency where it uses up the single
|
||||||
|
// user-defined conversion allowed by C++ during initialization. This can
|
||||||
|
// cause problems in some API edge cases. For instance, in scoped_ptr, it is
|
||||||
|
// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a
|
||||||
|
// value of type scoped_ptr<Child> even if you add a constructor to
|
||||||
|
// scoped_ptr<> that would make it look like it should work. C++11 does not
|
||||||
|
// have this deficiency.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// COMPARED TO Boost.Move
|
||||||
|
//
|
||||||
|
// Our implementation similar to Boost.Move, but we keep the RValue struct
|
||||||
|
// private to the move-only type, and we don't use the reinterpret_cast<> hack.
|
||||||
|
//
|
||||||
|
// In Boost.Move, RValue is the boost::rv<> template. This type can be used
|
||||||
|
// when writing APIs like:
|
||||||
|
//
|
||||||
|
// void MyFunc(boost::rv<Foo>& f)
|
||||||
|
//
|
||||||
|
// that can take advantage of rv<> to avoid extra copies of a type. However you
|
||||||
|
// would still be able to call this version of MyFunc with an l-value:
|
||||||
|
//
|
||||||
|
// Foo f;
|
||||||
|
// MyFunc(f); // Uh oh, we probably just destroyed |f| w/o calling Pass().
|
||||||
|
//
|
||||||
|
// unless someone is very careful to also declare a parallel override like:
|
||||||
|
//
|
||||||
|
// void MyFunc(const Foo& f)
|
||||||
|
//
|
||||||
|
// that would catch the l-values first. This was declared unsafe in C++11 and
|
||||||
|
// a C++11 compiler will explicitly fail MyFunc(f). Unfortunately, we cannot
|
||||||
|
// ensure this in C++03.
|
||||||
|
//
|
||||||
|
// Since we have no need for writing such APIs yet, our implementation keeps
|
||||||
|
// RValue private and uses a .Pass() method to do the conversion instead of
|
||||||
|
// trying to write a version of "std::move()." Writing an API like std::move()
|
||||||
|
// would require the RValue struct to be public.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// CAVEATS
|
||||||
|
//
|
||||||
|
// If you include a move-only type as a field inside a class that does not
|
||||||
|
// explicitly declare a copy constructor, the containing class's implicit
|
||||||
|
// copy constructor will change from Containing(const Containing&) to
|
||||||
|
// Containing(Containing&). This can cause some unexpected errors.
|
||||||
|
//
|
||||||
|
// http://llvm.org/bugs/show_bug.cgi?id=11528
|
||||||
|
//
|
||||||
|
// The workaround is to explicitly declare your copy constructor.
|
||||||
|
//
|
||||||
|
#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \
|
||||||
|
private: \
|
||||||
|
struct rvalue_type { \
|
||||||
|
explicit rvalue_type(type* object) : object(object) {} \
|
||||||
|
type* object; \
|
||||||
|
}; \
|
||||||
|
type(type&); \
|
||||||
|
void operator=(type&); \
|
||||||
|
public: \
|
||||||
|
operator rvalue_type() { return rvalue_type(this); } \
|
||||||
|
type Pass() { return type(rvalue_type(this)); } \
|
||||||
|
private:
|
||||||
|
|
||||||
|
#endif // THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_
|
@ -149,7 +149,7 @@ void NATServer::OnExternalPacket(
|
|||||||
|
|
||||||
// Forward this packet to the internal address.
|
// Forward this packet to the internal address.
|
||||||
// First prepend the address in a quasi-STUN format.
|
// First prepend the address in a quasi-STUN format.
|
||||||
scoped_array<char> real_buf(new char[size + kNATEncodedIPv6AddressSize]);
|
scoped_ptr<char[]> real_buf(new char[size + kNATEncodedIPv6AddressSize]);
|
||||||
size_t addrlength = PackAddressForNAT(real_buf.get(),
|
size_t addrlength = PackAddressForNAT(real_buf.get(),
|
||||||
size + kNATEncodedIPv6AddressSize,
|
size + kNATEncodedIPv6AddressSize,
|
||||||
remote_addr);
|
remote_addr);
|
||||||
|
@ -154,7 +154,7 @@ class NATSocket : public AsyncSocket, public sigslot::has_slots<> {
|
|||||||
return socket_->SendTo(data, size, addr);
|
return socket_->SendTo(data, size, addr);
|
||||||
}
|
}
|
||||||
// This array will be too large for IPv4 packets, but only by 12 bytes.
|
// This array will be too large for IPv4 packets, but only by 12 bytes.
|
||||||
scoped_array<char> buf(new char[size + kNATEncodedIPv6AddressSize]);
|
scoped_ptr<char[]> buf(new char[size + kNATEncodedIPv6AddressSize]);
|
||||||
size_t addrlength = PackAddressForNAT(buf.get(),
|
size_t addrlength = PackAddressForNAT(buf.get(),
|
||||||
size + kNATEncodedIPv6AddressSize,
|
size + kNATEncodedIPv6AddressSize,
|
||||||
addr);
|
addr);
|
||||||
|
@ -109,7 +109,7 @@ bool HasIPv6Enabled() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DWORD protbuff_size = 4096;
|
DWORD protbuff_size = 4096;
|
||||||
scoped_array<char> protocols;
|
scoped_ptr<char[]> protocols;
|
||||||
LPWSAPROTOCOL_INFOW protocol_infos = NULL;
|
LPWSAPROTOCOL_INFOW protocol_infos = NULL;
|
||||||
int requested_protocols[2] = {AF_INET6, 0};
|
int requested_protocols[2] = {AF_INET6, 0};
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ bool BasicNetworkManager::CreateNetworks(bool include_ignored,
|
|||||||
NetworkMap current_networks;
|
NetworkMap current_networks;
|
||||||
// MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses.
|
// MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses.
|
||||||
size_t buffer_size = 16384;
|
size_t buffer_size = 16384;
|
||||||
scoped_array<char> adapter_info(new char[buffer_size]);
|
scoped_ptr<char[]> adapter_info(new char[buffer_size]);
|
||||||
PIP_ADAPTER_ADDRESSES adapter_addrs =
|
PIP_ADAPTER_ADDRESSES adapter_addrs =
|
||||||
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
|
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
|
||||||
int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST |
|
int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST |
|
||||||
|
@ -120,7 +120,8 @@ TEST_F(NetworkTest, TestIgnoreList) {
|
|||||||
EXPECT_FALSE(IsIgnoredNetwork(network_manager, include_me));
|
EXPECT_FALSE(IsIgnoredNetwork(network_manager, include_me));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(NetworkTest, TestCreateNetworks) {
|
// Test is failing on Windows opt: b/11288214
|
||||||
|
TEST_F(NetworkTest, DISABLED_TestCreateNetworks) {
|
||||||
BasicNetworkManager manager;
|
BasicNetworkManager manager;
|
||||||
NetworkManager::NetworkList result = GetNetworks(manager, true);
|
NetworkManager::NetworkList result = GetNetworks(manager, true);
|
||||||
// We should be able to bind to any addresses we find.
|
// We should be able to bind to any addresses we find.
|
||||||
|
@ -534,6 +534,9 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
|
|||||||
*slevel = IPPROTO_TCP;
|
*slevel = IPPROTO_TCP;
|
||||||
*sopt = TCP_NODELAY;
|
*sopt = TCP_NODELAY;
|
||||||
break;
|
break;
|
||||||
|
case OPT_DSCP:
|
||||||
|
LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
|
||||||
|
return -1;
|
||||||
default:
|
default:
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,34 +1,102 @@
|
|||||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
// Borrowed from chromium.
|
||||||
// Copyright (c) 2001, 2002 Peter Dimov
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
//
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// Permission to copy, use, modify, sell and distribute this software
|
// found in the LICENSE file.
|
||||||
// is granted provided this copyright notice appears in all copies.
|
|
||||||
// This software is provided "as is" without express or implied
|
|
||||||
// warranty, and with no claim as to its suitability for any purpose.
|
|
||||||
//
|
|
||||||
// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
|
|
||||||
//
|
|
||||||
|
|
||||||
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
// Scopers help you manage ownership of a pointer, helping you easily manage the
|
||||||
// of the object pointed to, either on destruction of the scoped_ptr or via
|
// a pointer within a scope, and automatically destroying the pointer at the
|
||||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
// end of a scope. There are two main classes you will use, which correspond
|
||||||
// use shared_ptr or std::auto_ptr if your needs are more complex.
|
// to the operators new/delete and new[]/delete[].
|
||||||
|
//
|
||||||
|
// Example usage (scoped_ptr<T>):
|
||||||
|
// {
|
||||||
|
// scoped_ptr<Foo> foo(new Foo("wee"));
|
||||||
|
// } // foo goes out of scope, releasing the pointer with it.
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// scoped_ptr<Foo> foo; // No pointer managed.
|
||||||
|
// foo.reset(new Foo("wee")); // Now a pointer is managed.
|
||||||
|
// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
|
||||||
|
// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
|
||||||
|
// foo->Method(); // Foo::Method() called.
|
||||||
|
// foo.get()->Method(); // Foo::Method() called.
|
||||||
|
// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
|
||||||
|
// // manages a pointer.
|
||||||
|
// foo.reset(new Foo("wee4")); // foo manages a pointer again.
|
||||||
|
// foo.reset(); // Foo("wee4") destroyed, foo no longer
|
||||||
|
// // manages a pointer.
|
||||||
|
// } // foo wasn't managing a pointer, so nothing was destroyed.
|
||||||
|
//
|
||||||
|
// Example usage (scoped_ptr<T[]>):
|
||||||
|
// {
|
||||||
|
// scoped_ptr<Foo[]> foo(new Foo[100]);
|
||||||
|
// foo.get()->Method(); // Foo::Method on the 0th element.
|
||||||
|
// foo[10].Method(); // Foo::Method on the 10th element.
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// These scopers also implement part of the functionality of C++11 unique_ptr
|
||||||
|
// in that they are "movable but not copyable." You can use the scopers in
|
||||||
|
// the parameter and return types of functions to signify ownership transfer
|
||||||
|
// in to and out of a function. When calling a function that has a scoper
|
||||||
|
// as the argument type, it must be called with the result of an analogous
|
||||||
|
// scoper's Pass() function or another function that generates a temporary;
|
||||||
|
// passing by copy will NOT work. Here is an example using scoped_ptr:
|
||||||
|
//
|
||||||
|
// void TakesOwnership(scoped_ptr<Foo> arg) {
|
||||||
|
// // Do something with arg
|
||||||
|
// }
|
||||||
|
// scoped_ptr<Foo> CreateFoo() {
|
||||||
|
// // No need for calling Pass() because we are constructing a temporary
|
||||||
|
// // for the return value.
|
||||||
|
// return scoped_ptr<Foo>(new Foo("new"));
|
||||||
|
// }
|
||||||
|
// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
|
||||||
|
// return arg.Pass();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
|
||||||
|
// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
|
||||||
|
// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
|
||||||
|
// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
|
||||||
|
// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL.
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Notice that if you do not call Pass() when returning from PassThru(), or
|
||||||
|
// when invoking TakesOwnership(), the code will not compile because scopers
|
||||||
|
// are not copyable; they only implement move semantics which require calling
|
||||||
|
// the Pass() function to signify a destructive transfer of state. CreateFoo()
|
||||||
|
// is different though because we are constructing a temporary on the return
|
||||||
|
// line and thus can avoid needing to call Pass().
|
||||||
|
//
|
||||||
|
// Pass() properly handles upcast in initialization, i.e. you can use a
|
||||||
|
// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
|
||||||
|
//
|
||||||
|
// scoped_ptr<Foo> foo(new Foo());
|
||||||
|
// scoped_ptr<FooParent> parent(foo.Pass());
|
||||||
|
//
|
||||||
|
// PassAs<>() should be used to upcast return value in return statement:
|
||||||
|
//
|
||||||
|
// scoped_ptr<Foo> CreateFoo() {
|
||||||
|
// scoped_ptr<FooChild> result(new FooChild());
|
||||||
|
// return result.PassAs<Foo>();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
|
||||||
|
// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
|
||||||
|
|
||||||
// scoped_ptr_malloc added in by Google. When one of
|
|
||||||
// these goes out of scope, instead of doing a delete or delete[], it
|
|
||||||
// calls free(). scoped_ptr_malloc<char> is likely to see much more
|
|
||||||
// use than any other specializations.
|
|
||||||
|
|
||||||
// release() added in by Google. Use this to conditionally
|
|
||||||
// transfer ownership of a heap-allocated object to the caller, usually on
|
|
||||||
// method success.
|
|
||||||
#ifndef TALK_BASE_SCOPED_PTR_H__
|
#ifndef TALK_BASE_SCOPED_PTR_H__
|
||||||
#define TALK_BASE_SCOPED_PTR_H__
|
#define TALK_BASE_SCOPED_PTR_H__
|
||||||
|
|
||||||
#include <cstddef> // for std::ptrdiff_t
|
#include <cstddef> // for std::ptrdiff_t
|
||||||
#include <stdlib.h> // for free() decl
|
#include <stdlib.h> // for free() decl
|
||||||
|
|
||||||
|
#include <algorithm> // For std::swap().
|
||||||
|
|
||||||
#include "talk/base/common.h" // for ASSERT
|
#include "talk/base/common.h" // for ASSERT
|
||||||
|
#include "talk/base/compile_assert.h" // for COMPILE_ASSERT
|
||||||
|
#include "talk/base/move.h" // for MOVE_ONLY_TYPE_FOR_CPP_03
|
||||||
|
#include "talk/base/template_util.h" // for is_convertible, is_array
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
namespace std { using ::ptrdiff_t; };
|
namespace std { using ::ptrdiff_t; };
|
||||||
@ -36,242 +104,495 @@ namespace std { using ::ptrdiff_t; };
|
|||||||
|
|
||||||
namespace talk_base {
|
namespace talk_base {
|
||||||
|
|
||||||
template <typename T>
|
// Function object which deletes its parameter, which must be a pointer.
|
||||||
class scoped_ptr {
|
// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
|
||||||
private:
|
// invokes 'delete'. The default deleter for scoped_ptr<T>.
|
||||||
|
template <class T>
|
||||||
T* ptr;
|
struct DefaultDeleter {
|
||||||
|
DefaultDeleter() {}
|
||||||
scoped_ptr(scoped_ptr const &);
|
template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
|
||||||
scoped_ptr & operator=(scoped_ptr const &);
|
// IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
|
||||||
|
// if U* is implicitly convertible to T* and U is not an array type.
|
||||||
public:
|
//
|
||||||
|
// Correct implementation should use SFINAE to disable this
|
||||||
typedef T element_type;
|
// constructor. However, since there are no other 1-argument constructors,
|
||||||
|
// using a COMPILE_ASSERT() based on is_convertible<> and requiring
|
||||||
explicit scoped_ptr(T* p = NULL): ptr(p) {}
|
// complete types is simpler and will cause compile failures for equivalent
|
||||||
|
// misuses.
|
||||||
~scoped_ptr() {
|
//
|
||||||
typedef char type_must_be_complete[sizeof(T)];
|
// Note, the is_convertible<U*, T*> check also ensures that U is not an
|
||||||
|
// array. T is guaranteed to be a non-array, so any U* where U is an array
|
||||||
|
// cannot convert to T*.
|
||||||
|
enum { T_must_be_complete = sizeof(T) };
|
||||||
|
enum { U_must_be_complete = sizeof(U) };
|
||||||
|
COMPILE_ASSERT((talk_base::is_convertible<U*, T*>::value),
|
||||||
|
U_ptr_must_implicitly_convert_to_T_ptr);
|
||||||
|
}
|
||||||
|
inline void operator()(T* ptr) const {
|
||||||
|
enum { type_must_be_complete = sizeof(T) };
|
||||||
delete ptr;
|
delete ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(T* p = NULL) {
|
|
||||||
typedef char type_must_be_complete[sizeof(T)];
|
|
||||||
|
|
||||||
if (ptr != p) {
|
|
||||||
T* obj = ptr;
|
|
||||||
ptr = p;
|
|
||||||
// Delete last, in case obj destructor indirectly results in ~scoped_ptr
|
|
||||||
delete obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator*() const {
|
|
||||||
ASSERT(ptr != NULL);
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator->() const {
|
|
||||||
ASSERT(ptr != NULL);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* get() const {
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(scoped_ptr & b) {
|
|
||||||
T* tmp = b.ptr;
|
|
||||||
b.ptr = ptr;
|
|
||||||
ptr = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* release() {
|
|
||||||
T* tmp = ptr;
|
|
||||||
ptr = NULL;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
T** accept() {
|
|
||||||
if (ptr) {
|
|
||||||
delete ptr;
|
|
||||||
ptr = NULL;
|
|
||||||
}
|
|
||||||
return &ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
T** use() {
|
|
||||||
return &ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow scoped_ptr<T> to be used in boolean expressions, but not
|
|
||||||
// implicitly convertible to a real bool (which is dangerous).
|
|
||||||
// Borrowed from chromium's scoped_ptr implementation.
|
|
||||||
typedef T* scoped_ptr::*Testable;
|
|
||||||
operator Testable() const { return ptr ? &scoped_ptr::ptr : NULL; }
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> inline
|
// Specialization of DefaultDeleter for array types.
|
||||||
void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
|
template <class T>
|
||||||
a.swap(b);
|
struct DefaultDeleter<T[]> {
|
||||||
}
|
inline void operator()(T* ptr) const {
|
||||||
|
enum { type_must_be_complete = sizeof(T) };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
|
|
||||||
// is guaranteed, either on destruction of the scoped_array or via an explicit
|
|
||||||
// reset(). Use shared_array or std::vector if your needs are more complex.
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class scoped_array {
|
|
||||||
private:
|
|
||||||
|
|
||||||
T* ptr;
|
|
||||||
|
|
||||||
scoped_array(scoped_array const &);
|
|
||||||
scoped_array & operator=(scoped_array const &);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef T element_type;
|
|
||||||
|
|
||||||
explicit scoped_array(T* p = NULL) : ptr(p) {}
|
|
||||||
|
|
||||||
~scoped_array() {
|
|
||||||
typedef char type_must_be_complete[sizeof(T)];
|
|
||||||
delete[] ptr;
|
delete[] ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(T* p = NULL) {
|
private:
|
||||||
typedef char type_must_be_complete[sizeof(T)];
|
// Disable this operator for any U != T because it is undefined to execute
|
||||||
|
// an array delete when the static type of the array mismatches the dynamic
|
||||||
|
// type.
|
||||||
|
//
|
||||||
|
// References:
|
||||||
|
// C++98 [expr.delete]p3
|
||||||
|
// http://cplusplus.github.com/LWG/lwg-defects.html#938
|
||||||
|
template <typename U> void operator()(U* array) const;
|
||||||
|
};
|
||||||
|
|
||||||
if (ptr != p) {
|
template <class T, int n>
|
||||||
T* arr = ptr;
|
struct DefaultDeleter<T[n]> {
|
||||||
ptr = p;
|
// Never allow someone to declare something like scoped_ptr<int[10]>.
|
||||||
// Delete last, in case arr destructor indirectly results in ~scoped_array
|
COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
|
||||||
delete [] arr;
|
};
|
||||||
|
|
||||||
|
// Function object which invokes 'free' on its parameter, which must be
|
||||||
|
// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
|
||||||
|
//
|
||||||
|
// scoped_ptr<int, talk_base::FreeDeleter> foo_ptr(
|
||||||
|
// static_cast<int*>(malloc(sizeof(int))));
|
||||||
|
struct FreeDeleter {
|
||||||
|
inline void operator()(void* ptr) const {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Minimal implementation of the core logic of scoped_ptr, suitable for
|
||||||
|
// reuse in both scoped_ptr and its specializations.
|
||||||
|
template <class T, class D>
|
||||||
|
class scoped_ptr_impl {
|
||||||
|
public:
|
||||||
|
explicit scoped_ptr_impl(T* p) : data_(p) { }
|
||||||
|
|
||||||
|
// Initializer for deleters that have data parameters.
|
||||||
|
scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
|
||||||
|
|
||||||
|
// Templated constructor that destructively takes the value from another
|
||||||
|
// scoped_ptr_impl.
|
||||||
|
template <typename U, typename V>
|
||||||
|
scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
|
||||||
|
: data_(other->release(), other->get_deleter()) {
|
||||||
|
// We do not support move-only deleters. We could modify our move
|
||||||
|
// emulation to have talk_base::subtle::move() and
|
||||||
|
// talk_base::subtle::forward()
|
||||||
|
// functions that are imperfect emulations of their C++11 equivalents,
|
||||||
|
// but until there's a requirement, just assume deleters are copyable.
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, typename V>
|
||||||
|
void TakeState(scoped_ptr_impl<U, V>* other) {
|
||||||
|
// See comment in templated constructor above regarding lack of support
|
||||||
|
// for move-only deleters.
|
||||||
|
reset(other->release());
|
||||||
|
get_deleter() = other->get_deleter();
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_ptr_impl() {
|
||||||
|
if (data_.ptr != NULL) {
|
||||||
|
// Not using get_deleter() saves one function call in non-optimized
|
||||||
|
// builds.
|
||||||
|
static_cast<D&>(data_)(data_.ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](std::ptrdiff_t i) const {
|
void reset(T* p) {
|
||||||
ASSERT(ptr != NULL);
|
// This is a self-reset, which is no longer allowed: http://crbug.com/162971
|
||||||
ASSERT(i >= 0);
|
if (p != NULL && p == data_.ptr)
|
||||||
return ptr[i];
|
abort();
|
||||||
|
|
||||||
|
// Note that running data_.ptr = p can lead to undefined behavior if
|
||||||
|
// get_deleter()(get()) deletes this. In order to pevent this, reset()
|
||||||
|
// should update the stored pointer before deleting its old value.
|
||||||
|
//
|
||||||
|
// However, changing reset() to use that behavior may cause current code to
|
||||||
|
// break in unexpected ways. If the destruction of the owned object
|
||||||
|
// dereferences the scoped_ptr when it is destroyed by a call to reset(),
|
||||||
|
// then it will incorrectly dispatch calls to |p| rather than the original
|
||||||
|
// value of |data_.ptr|.
|
||||||
|
//
|
||||||
|
// During the transition period, set the stored pointer to NULL while
|
||||||
|
// deleting the object. Eventually, this safety check will be removed to
|
||||||
|
// prevent the scenario initially described from occuring and
|
||||||
|
// http://crbug.com/176091 can be closed.
|
||||||
|
T* old = data_.ptr;
|
||||||
|
data_.ptr = NULL;
|
||||||
|
if (old != NULL)
|
||||||
|
static_cast<D&>(data_)(old);
|
||||||
|
data_.ptr = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* get() const {
|
T* get() const { return data_.ptr; }
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(scoped_array & b) {
|
D& get_deleter() { return data_; }
|
||||||
T* tmp = b.ptr;
|
const D& get_deleter() const { return data_; }
|
||||||
b.ptr = ptr;
|
|
||||||
ptr = tmp;
|
void swap(scoped_ptr_impl& p2) {
|
||||||
|
// Standard swap idiom: 'using std::swap' ensures that std::swap is
|
||||||
|
// present in the overload set, but we call swap unqualified so that
|
||||||
|
// any more-specific overloads can be used, if available.
|
||||||
|
using std::swap;
|
||||||
|
swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
|
||||||
|
swap(data_.ptr, p2.data_.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
T* release() {
|
T* release() {
|
||||||
T* tmp = ptr;
|
T* old_ptr = data_.ptr;
|
||||||
ptr = NULL;
|
data_.ptr = NULL;
|
||||||
return tmp;
|
return old_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
T** accept() {
|
T** accept() {
|
||||||
if (ptr) {
|
reset(NULL);
|
||||||
delete [] ptr;
|
return &(data_.ptr);
|
||||||
ptr = NULL;
|
|
||||||
}
|
|
||||||
return &ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow scoped_array<T> to be used in boolean expressions, but not
|
T** use() {
|
||||||
// implicitly convertible to a real bool (which is dangerous).
|
return &(data_.ptr);
|
||||||
// Borrowed from chromium's scoped_array implementation.
|
}
|
||||||
typedef T* scoped_array::*Testable;
|
|
||||||
operator Testable() const { return ptr ? &scoped_array::ptr : NULL; }
|
private:
|
||||||
|
// Needed to allow type-converting constructor.
|
||||||
|
template <typename U, typename V> friend class scoped_ptr_impl;
|
||||||
|
|
||||||
|
// Use the empty base class optimization to allow us to have a D
|
||||||
|
// member, while avoiding any space overhead for it when D is an
|
||||||
|
// empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
|
||||||
|
// discussion of this technique.
|
||||||
|
struct Data : public D {
|
||||||
|
explicit Data(T* ptr_in) : ptr(ptr_in) {}
|
||||||
|
Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
|
||||||
|
T* ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
Data data_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> inline
|
} // namespace internal
|
||||||
void swap(scoped_array<T>& a, scoped_array<T>& b) {
|
|
||||||
a.swap(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
|
// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
|
||||||
// second template argument, the function used to free the object.
|
// automatically deletes the pointer it holds (if any).
|
||||||
|
// That is, scoped_ptr<T> owns the T object that it points to.
|
||||||
template<typename T, void (*FF)(T*) = free> class scoped_ptr_malloc {
|
// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
|
||||||
private:
|
// Also like T*, scoped_ptr<T> is thread-compatible, and once you
|
||||||
|
// dereference it, you get the thread safety guarantees of T.
|
||||||
T* ptr;
|
//
|
||||||
|
// The size of scoped_ptr is small. On most compilers, when using the
|
||||||
scoped_ptr_malloc(scoped_ptr_malloc const &);
|
// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
|
||||||
scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
|
// increase the size proportional to whatever state they need to have. See
|
||||||
|
// comments inside scoped_ptr_impl<> for details.
|
||||||
|
//
|
||||||
|
// Current implementation targets having a strict subset of C++11's
|
||||||
|
// unique_ptr<> features. Known deficiencies include not supporting move-only
|
||||||
|
// deleteres, function pointers as deleters, and deleters with reference
|
||||||
|
// types.
|
||||||
|
template <class T, class D = talk_base::DefaultDeleter<T> >
|
||||||
|
class scoped_ptr {
|
||||||
|
MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// The element and deleter types.
|
||||||
typedef T element_type;
|
typedef T element_type;
|
||||||
|
typedef D deleter_type;
|
||||||
|
|
||||||
explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
|
// Constructor. Defaults to initializing with NULL.
|
||||||
|
scoped_ptr() : impl_(NULL) { }
|
||||||
|
|
||||||
~scoped_ptr_malloc() {
|
// Constructor. Takes ownership of p.
|
||||||
FF(ptr);
|
explicit scoped_ptr(element_type* p) : impl_(p) { }
|
||||||
|
|
||||||
|
// Constructor. Allows initialization of a stateful deleter.
|
||||||
|
scoped_ptr(element_type* p, const D& d) : impl_(p, d) { }
|
||||||
|
|
||||||
|
// Constructor. Allows construction from a scoped_ptr rvalue for a
|
||||||
|
// convertible type and deleter.
|
||||||
|
//
|
||||||
|
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
|
||||||
|
// from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
|
||||||
|
// has different post-conditions if D is a reference type. Since this
|
||||||
|
// implementation does not support deleters with reference type,
|
||||||
|
// we do not need a separate move constructor allowing us to avoid one
|
||||||
|
// use of SFINAE. You only need to care about this if you modify the
|
||||||
|
// implementation of scoped_ptr.
|
||||||
|
template <typename U, typename V>
|
||||||
|
scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {
|
||||||
|
COMPILE_ASSERT(!talk_base::is_array<U>::value, U_cannot_be_an_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(T* p = 0) {
|
// Constructor. Move constructor for C++03 move emulation of this type.
|
||||||
if (ptr != p) {
|
scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
|
||||||
FF(ptr);
|
|
||||||
ptr = p;
|
// operator=. Allows assignment from a scoped_ptr rvalue for a convertible
|
||||||
}
|
// type and deleter.
|
||||||
|
//
|
||||||
|
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
|
||||||
|
// the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
|
||||||
|
// form has different requirements on for move-only Deleters. Since this
|
||||||
|
// implementation does not support move-only Deleters, we do not need a
|
||||||
|
// separate move assignment operator allowing us to avoid one use of SFINAE.
|
||||||
|
// You only need to care about this if you modify the implementation of
|
||||||
|
// scoped_ptr.
|
||||||
|
template <typename U, typename V>
|
||||||
|
scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
|
||||||
|
COMPILE_ASSERT(!talk_base::is_array<U>::value, U_cannot_be_an_array);
|
||||||
|
impl_.TakeState(&rhs.impl_);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator*() const {
|
// Reset. Deletes the currently owned object, if any.
|
||||||
ASSERT(ptr != 0);
|
// Then takes ownership of a new object, if given.
|
||||||
return *ptr;
|
void reset(element_type* p = NULL) { impl_.reset(p); }
|
||||||
}
|
|
||||||
|
|
||||||
T* operator->() const {
|
// Accessors to get the owned object.
|
||||||
ASSERT(ptr != 0);
|
// operator* and operator-> will assert() if there is no current object.
|
||||||
return ptr;
|
element_type& operator*() const {
|
||||||
|
ASSERT(impl_.get() != NULL);
|
||||||
|
return *impl_.get();
|
||||||
}
|
}
|
||||||
|
element_type* operator->() const {
|
||||||
|
ASSERT(impl_.get() != NULL);
|
||||||
|
return impl_.get();
|
||||||
|
}
|
||||||
|
element_type* get() const { return impl_.get(); }
|
||||||
|
|
||||||
T* get() const {
|
// Access to the deleter.
|
||||||
return ptr;
|
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||||
}
|
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||||
|
|
||||||
void swap(scoped_ptr_malloc & b) {
|
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||||
T* tmp = b.ptr;
|
|
||||||
b.ptr = ptr;
|
|
||||||
ptr = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* release() {
|
|
||||||
T* tmp = ptr;
|
|
||||||
ptr = 0;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
T** accept() {
|
|
||||||
if (ptr) {
|
|
||||||
FF(ptr);
|
|
||||||
ptr = 0;
|
|
||||||
}
|
|
||||||
return &ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow scoped_ptr_malloc<T> to be used in boolean expressions, but not
|
|
||||||
// implicitly convertible to a real bool (which is dangerous).
|
// implicitly convertible to a real bool (which is dangerous).
|
||||||
// Borrowed from chromium's scoped_ptr_malloc implementation.
|
//
|
||||||
typedef T* scoped_ptr_malloc::*Testable;
|
// Note that this trick is only safe when the == and != operators
|
||||||
operator Testable() const { return ptr ? &scoped_ptr_malloc::ptr : NULL; }
|
// are declared explicitly, as otherwise "scoped_ptr1 ==
|
||||||
|
// scoped_ptr2" will compile but do the wrong thing (i.e., convert
|
||||||
|
// to Testable and then do the comparison).
|
||||||
|
private:
|
||||||
|
typedef talk_base::internal::scoped_ptr_impl<element_type, deleter_type>
|
||||||
|
scoped_ptr::*Testable;
|
||||||
|
|
||||||
|
public:
|
||||||
|
operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
|
||||||
|
|
||||||
|
// Comparison operators.
|
||||||
|
// These return whether two scoped_ptr refer to the same object, not just to
|
||||||
|
// two different but equal objects.
|
||||||
|
bool operator==(const element_type* p) const { return impl_.get() == p; }
|
||||||
|
bool operator!=(const element_type* p) const { return impl_.get() != p; }
|
||||||
|
|
||||||
|
// Swap two scoped pointers.
|
||||||
|
void swap(scoped_ptr& p2) {
|
||||||
|
impl_.swap(p2.impl_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release a pointer.
|
||||||
|
// The return value is the current pointer held by this object.
|
||||||
|
// If this object holds a NULL pointer, the return value is NULL.
|
||||||
|
// After this operation, this object will hold a NULL pointer,
|
||||||
|
// and will not own the object any more.
|
||||||
|
element_type* release() WARN_UNUSED_RESULT {
|
||||||
|
return impl_.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the currently held pointer and return a pointer
|
||||||
|
// to allow overwriting of the current pointer address.
|
||||||
|
element_type** accept() WARN_UNUSED_RESULT {
|
||||||
|
return impl_.accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a pointer to the current pointer address.
|
||||||
|
element_type** use() WARN_UNUSED_RESULT {
|
||||||
|
return impl_.use();
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++98 doesn't support functions templates with default parameters which
|
||||||
|
// makes it hard to write a PassAs() that understands converting the deleter
|
||||||
|
// while preserving simple calling semantics.
|
||||||
|
//
|
||||||
|
// Until there is a use case for PassAs() with custom deleters, just ignore
|
||||||
|
// the custom deleter.
|
||||||
|
template <typename PassAsType>
|
||||||
|
scoped_ptr<PassAsType> PassAs() {
|
||||||
|
return scoped_ptr<PassAsType>(Pass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Needed to reach into |impl_| in the constructor.
|
||||||
|
template <typename U, typename V> friend class scoped_ptr;
|
||||||
|
talk_base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
|
||||||
|
|
||||||
|
// Forbidden for API compatibility with std::unique_ptr.
|
||||||
|
explicit scoped_ptr(int disallow_construction_from_null);
|
||||||
|
|
||||||
|
// Forbid comparison of scoped_ptr types. If U != T, it totally
|
||||||
|
// doesn't make sense, and if U == T, it still doesn't make sense
|
||||||
|
// because you should never have the same object owned by two different
|
||||||
|
// scoped_ptrs.
|
||||||
|
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
|
||||||
|
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, void (*FF)(T*)> inline
|
template <class T, class D>
|
||||||
void swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& b) {
|
class scoped_ptr<T[], D> {
|
||||||
a.swap(b);
|
MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
|
||||||
}
|
|
||||||
|
public:
|
||||||
|
// The element and deleter types.
|
||||||
|
typedef T element_type;
|
||||||
|
typedef D deleter_type;
|
||||||
|
|
||||||
|
// Constructor. Defaults to initializing with NULL.
|
||||||
|
scoped_ptr() : impl_(NULL) { }
|
||||||
|
|
||||||
|
// Constructor. Stores the given array. Note that the argument's type
|
||||||
|
// must exactly match T*. In particular:
|
||||||
|
// - it cannot be a pointer to a type derived from T, because it is
|
||||||
|
// inherently unsafe in the general case to access an array through a
|
||||||
|
// pointer whose dynamic type does not match its static type (eg., if
|
||||||
|
// T and the derived types had different sizes access would be
|
||||||
|
// incorrectly calculated). Deletion is also always undefined
|
||||||
|
// (C++98 [expr.delete]p3). If you're doing this, fix your code.
|
||||||
|
// - it cannot be NULL, because NULL is an integral expression, not a
|
||||||
|
// pointer to T. Use the no-argument version instead of explicitly
|
||||||
|
// passing NULL.
|
||||||
|
// - it cannot be const-qualified differently from T per unique_ptr spec
|
||||||
|
// (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
|
||||||
|
// to work around this may use implicit_cast<const T*>().
|
||||||
|
// However, because of the first bullet in this comment, users MUST
|
||||||
|
// NOT use implicit_cast<Base*>() to upcast the static type of the array.
|
||||||
|
explicit scoped_ptr(element_type* array) : impl_(array) { }
|
||||||
|
|
||||||
|
// Constructor. Move constructor for C++03 move emulation of this type.
|
||||||
|
scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
|
||||||
|
|
||||||
|
// operator=. Move operator= for C++03 move emulation of this type.
|
||||||
|
scoped_ptr& operator=(RValue rhs) {
|
||||||
|
impl_.TakeState(&rhs.object->impl_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset. Deletes the currently owned array, if any.
|
||||||
|
// Then takes ownership of a new object, if given.
|
||||||
|
void reset(element_type* array = NULL) { impl_.reset(array); }
|
||||||
|
|
||||||
|
// Accessors to get the owned array.
|
||||||
|
element_type& operator[](size_t i) const {
|
||||||
|
ASSERT(impl_.get() != NULL);
|
||||||
|
return impl_.get()[i];
|
||||||
|
}
|
||||||
|
element_type* get() const { return impl_.get(); }
|
||||||
|
|
||||||
|
// Access to the deleter.
|
||||||
|
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||||
|
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||||
|
|
||||||
|
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||||
|
// implicitly convertible to a real bool (which is dangerous).
|
||||||
|
private:
|
||||||
|
typedef talk_base::internal::scoped_ptr_impl<element_type, deleter_type>
|
||||||
|
scoped_ptr::*Testable;
|
||||||
|
|
||||||
|
public:
|
||||||
|
operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
|
||||||
|
|
||||||
|
// Comparison operators.
|
||||||
|
// These return whether two scoped_ptr refer to the same object, not just to
|
||||||
|
// two different but equal objects.
|
||||||
|
bool operator==(element_type* array) const { return impl_.get() == array; }
|
||||||
|
bool operator!=(element_type* array) const { return impl_.get() != array; }
|
||||||
|
|
||||||
|
// Swap two scoped pointers.
|
||||||
|
void swap(scoped_ptr& p2) {
|
||||||
|
impl_.swap(p2.impl_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release a pointer.
|
||||||
|
// The return value is the current pointer held by this object.
|
||||||
|
// If this object holds a NULL pointer, the return value is NULL.
|
||||||
|
// After this operation, this object will hold a NULL pointer,
|
||||||
|
// and will not own the object any more.
|
||||||
|
element_type* release() WARN_UNUSED_RESULT {
|
||||||
|
return impl_.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the currently held pointer and return a pointer
|
||||||
|
// to allow overwriting of the current pointer address.
|
||||||
|
element_type** accept() WARN_UNUSED_RESULT {
|
||||||
|
return impl_.accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a pointer to the current pointer address.
|
||||||
|
element_type** use() WARN_UNUSED_RESULT {
|
||||||
|
return impl_.use();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Force element_type to be a complete type.
|
||||||
|
enum { type_must_be_complete = sizeof(element_type) };
|
||||||
|
|
||||||
|
// Actually hold the data.
|
||||||
|
talk_base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
|
||||||
|
|
||||||
|
// Disable initialization from any type other than element_type*, by
|
||||||
|
// providing a constructor that matches such an initialization, but is
|
||||||
|
// private and has no definition. This is disabled because it is not safe to
|
||||||
|
// call delete[] on an array whose static type does not match its dynamic
|
||||||
|
// type.
|
||||||
|
template <typename U> explicit scoped_ptr(U* array);
|
||||||
|
explicit scoped_ptr(int disallow_construction_from_null);
|
||||||
|
|
||||||
|
// Disable reset() from any type other than element_type*, for the same
|
||||||
|
// reasons as the constructor above.
|
||||||
|
template <typename U> void reset(U* array);
|
||||||
|
void reset(int disallow_reset_from_null);
|
||||||
|
|
||||||
|
// Forbid comparison of scoped_ptr types. If U != T, it totally
|
||||||
|
// doesn't make sense, and if U == T, it still doesn't make sense
|
||||||
|
// because you should never have the same object owned by two different
|
||||||
|
// scoped_ptrs.
|
||||||
|
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
|
||||||
|
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace talk_base
|
} // namespace talk_base
|
||||||
|
|
||||||
|
// Free functions
|
||||||
|
template <class T, class D>
|
||||||
|
void swap(talk_base::scoped_ptr<T, D>& p1, talk_base::scoped_ptr<T, D>& p2) {
|
||||||
|
p1.swap(p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class D>
|
||||||
|
bool operator==(T* p1, const talk_base::scoped_ptr<T, D>& p2) {
|
||||||
|
return p1 == p2.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class D>
|
||||||
|
bool operator!=(T* p1, const talk_base::scoped_ptr<T, D>& p2) {
|
||||||
|
return p1 != p2.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// A function to convert T* into talk_base::scoped_ptr<T>
|
||||||
|
// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
|
||||||
|
// for talk_base::scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
|
||||||
|
template <typename T>
|
||||||
|
talk_base::scoped_ptr<T> make_scoped_ptr(T* ptr) {
|
||||||
|
return talk_base::scoped_ptr<T>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // #ifndef TALK_BASE_SCOPED_PTR_H__
|
#endif // #ifndef TALK_BASE_SCOPED_PTR_H__
|
||||||
|
@ -693,8 +693,8 @@ void SocketTest::TcpInternal(const IPAddress& loopback) {
|
|||||||
|
|
||||||
// Create test data.
|
// Create test data.
|
||||||
const size_t kDataSize = 1024 * 1024;
|
const size_t kDataSize = 1024 * 1024;
|
||||||
scoped_array<char> send_buffer(new char[kDataSize]);
|
scoped_ptr<char[]> send_buffer(new char[kDataSize]);
|
||||||
scoped_array<char> recv_buffer(new char[kDataSize]);
|
scoped_ptr<char[]> recv_buffer(new char[kDataSize]);
|
||||||
size_t send_pos = 0, recv_pos = 0;
|
size_t send_pos = 0, recv_pos = 0;
|
||||||
for (size_t i = 0; i < kDataSize; ++i) {
|
for (size_t i = 0; i < kDataSize; ++i) {
|
||||||
send_buffer[i] = static_cast<char>(i % 256);
|
send_buffer[i] = static_cast<char>(i % 256);
|
||||||
@ -934,7 +934,7 @@ void SocketTest::UdpReadyToSend(const IPAddress& loopback) {
|
|||||||
scoped_ptr<TestClient> client(
|
scoped_ptr<TestClient> client(
|
||||||
new TestClient(AsyncUDPSocket::Create(ss_, empty)));
|
new TestClient(AsyncUDPSocket::Create(ss_, empty)));
|
||||||
int test_packet_size = 1200;
|
int test_packet_size = 1200;
|
||||||
talk_base::scoped_array<char> test_packet(new char[test_packet_size]);
|
talk_base::scoped_ptr<char[]> test_packet(new char[test_packet_size]);
|
||||||
// Init the test packet just to avoid memcheck warning.
|
// Init the test packet just to avoid memcheck warning.
|
||||||
memset(test_packet.get(), 0, test_packet_size);
|
memset(test_packet.get(), 0, test_packet_size);
|
||||||
// Set the send buffer size to the same size as the test packet to have a
|
// Set the send buffer size to the same size as the test packet to have a
|
||||||
|
@ -57,7 +57,7 @@ const unsigned char kTestCertSha1[] = {0xA6, 0xC8, 0x59, 0xEA,
|
|||||||
class SSLIdentityTest : public testing::Test {
|
class SSLIdentityTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
SSLIdentityTest() :
|
SSLIdentityTest() :
|
||||||
identity1_(NULL), identity2_(NULL) {
|
identity1_(), identity2_() {
|
||||||
}
|
}
|
||||||
|
|
||||||
~SSLIdentityTest() {
|
~SSLIdentityTest() {
|
||||||
|
@ -166,7 +166,7 @@ StreamAdapterInterface::~StreamAdapterInterface() {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
StreamTap::StreamTap(StreamInterface* stream, StreamInterface* tap)
|
StreamTap::StreamTap(StreamInterface* stream, StreamInterface* tap)
|
||||||
: StreamAdapterInterface(stream), tap_(NULL), tap_result_(SR_SUCCESS),
|
: StreamAdapterInterface(stream), tap_(), tap_result_(SR_SUCCESS),
|
||||||
tap_error_(0) {
|
tap_error_(0) {
|
||||||
AttachTap(tap);
|
AttachTap(tap);
|
||||||
}
|
}
|
||||||
|
@ -691,7 +691,7 @@ class FifoBuffer : public StreamInterface {
|
|||||||
size_t offset, size_t* bytes_written);
|
size_t offset, size_t* bytes_written);
|
||||||
|
|
||||||
StreamState state_; // keeps the opened/closed state of the stream
|
StreamState state_; // keeps the opened/closed state of the stream
|
||||||
scoped_array<char> buffer_; // the allocated buffer
|
scoped_ptr<char[]> buffer_; // the allocated buffer
|
||||||
size_t buffer_length_; // size of the allocated buffer
|
size_t buffer_length_; // size of the allocated buffer
|
||||||
size_t data_length_; // amount of readable data in the buffer
|
size_t data_length_; // amount of readable data in the buffer
|
||||||
size_t read_position_; // offset to the readable data
|
size_t read_position_; // offset to the readable data
|
||||||
|
@ -74,7 +74,7 @@ static void GetProcessorInformation(int* physical_cpus, int* cache_size) {
|
|||||||
// Determine buffer size, allocate and get processor information.
|
// Determine buffer size, allocate and get processor information.
|
||||||
// Size can change between calls (unlikely), so a loop is done.
|
// Size can change between calls (unlikely), so a loop is done.
|
||||||
DWORD return_length = 0;
|
DWORD return_length = 0;
|
||||||
scoped_array<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> infos;
|
scoped_ptr<SYSTEM_LOGICAL_PROCESSOR_INFORMATION[]> infos;
|
||||||
while (!glpi(infos.get(), &return_length)) {
|
while (!glpi(infos.get(), &return_length)) {
|
||||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||||
infos.reset(new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[
|
infos.reset(new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[
|
||||||
@ -183,6 +183,8 @@ SystemInfo::SystemInfo()
|
|||||||
if (!sysctlbyname("machdep.cpu.stepping", &sysctl_value, &length, NULL, 0)) {
|
if (!sysctlbyname("machdep.cpu.stepping", &sysctl_value, &length, NULL, 0)) {
|
||||||
cpu_stepping_ = static_cast<int>(sysctl_value);
|
cpu_stepping_ = static_cast<int>(sysctl_value);
|
||||||
}
|
}
|
||||||
|
#elif defined(__native_client__)
|
||||||
|
// TODO(ryanpetrie): Implement this via PPAPI when it's available.
|
||||||
#else // LINUX || ANDROID
|
#else // LINUX || ANDROID
|
||||||
ProcCpuInfo proc_info;
|
ProcCpuInfo proc_info;
|
||||||
if (proc_info.LoadFromSystem()) {
|
if (proc_info.LoadFromSystem()) {
|
||||||
|
106
talk/base/template_util.h
Normal file
106
talk/base/template_util.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef TALK_BASE_TEMPLATE_UTIL_H_
|
||||||
|
#define TALK_BASE_TEMPLATE_UTIL_H_
|
||||||
|
|
||||||
|
#include <cstddef> // For size_t.
|
||||||
|
|
||||||
|
namespace talk_base {
|
||||||
|
|
||||||
|
// template definitions from tr1
|
||||||
|
|
||||||
|
template<class T, T v>
|
||||||
|
struct integral_constant {
|
||||||
|
static const T value = v;
|
||||||
|
typedef T value_type;
|
||||||
|
typedef integral_constant<T, v> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, T v> const T integral_constant<T, v>::value;
|
||||||
|
|
||||||
|
typedef integral_constant<bool, true> true_type;
|
||||||
|
typedef integral_constant<bool, false> false_type;
|
||||||
|
|
||||||
|
template <class T> struct is_pointer : false_type {};
|
||||||
|
template <class T> struct is_pointer<T*> : true_type {};
|
||||||
|
|
||||||
|
template <class T, class U> struct is_same : public false_type {};
|
||||||
|
template <class T> struct is_same<T,T> : true_type {};
|
||||||
|
|
||||||
|
template<class> struct is_array : public false_type {};
|
||||||
|
template<class T, size_t n> struct is_array<T[n]> : public true_type {};
|
||||||
|
template<class T> struct is_array<T[]> : public true_type {};
|
||||||
|
|
||||||
|
template <class T> struct is_non_const_reference : false_type {};
|
||||||
|
template <class T> struct is_non_const_reference<T&> : true_type {};
|
||||||
|
template <class T> struct is_non_const_reference<const T&> : false_type {};
|
||||||
|
|
||||||
|
template <class T> struct is_void : false_type {};
|
||||||
|
template <> struct is_void<void> : true_type {};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Types YesType and NoType are guaranteed such that sizeof(YesType) <
|
||||||
|
// sizeof(NoType).
|
||||||
|
typedef char YesType;
|
||||||
|
|
||||||
|
struct NoType {
|
||||||
|
YesType dummy[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class is an implementation detail for is_convertible, and you
|
||||||
|
// don't need to know how it works to use is_convertible. For those
|
||||||
|
// who care: we declare two different functions, one whose argument is
|
||||||
|
// of type To and one with a variadic argument list. We give them
|
||||||
|
// return types of different size, so we can use sizeof to trick the
|
||||||
|
// compiler into telling us which function it would have chosen if we
|
||||||
|
// had called it with an argument of type From. See Alexandrescu's
|
||||||
|
// _Modern C++ Design_ for more details on this sort of trick.
|
||||||
|
|
||||||
|
struct ConvertHelper {
|
||||||
|
template <typename To>
|
||||||
|
static YesType Test(To);
|
||||||
|
|
||||||
|
template <typename To>
|
||||||
|
static NoType Test(...);
|
||||||
|
|
||||||
|
template <typename From>
|
||||||
|
static From& Create();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to determine if a type is a struct/union/class. Inspired by Boost's
|
||||||
|
// is_class type_trait implementation.
|
||||||
|
struct IsClassHelper {
|
||||||
|
template <typename C>
|
||||||
|
static YesType Test(void(C::*)(void));
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
static NoType Test(...);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Inherits from true_type if From is convertible to To, false_type otherwise.
|
||||||
|
//
|
||||||
|
// Note that if the type is convertible, this will be a true_type REGARDLESS
|
||||||
|
// of whether or not the conversion would emit a warning.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct is_convertible
|
||||||
|
: integral_constant<bool,
|
||||||
|
sizeof(internal::ConvertHelper::Test<To>(
|
||||||
|
internal::ConvertHelper::Create<From>())) ==
|
||||||
|
sizeof(internal::YesType)> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_class
|
||||||
|
: integral_constant<bool,
|
||||||
|
sizeof(internal::IsClassHelper::Test<T>(0)) ==
|
||||||
|
sizeof(internal::YesType)> {
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace talk_base
|
||||||
|
|
||||||
|
#endif // TALK_BASE_TEMPLATE_UTIL_H_
|
@ -111,7 +111,7 @@ bool Win32Filesystem::CreatePrivateFile(const Pathname &filename) {
|
|||||||
&token_user_size);
|
&token_user_size);
|
||||||
|
|
||||||
// Get the TOKEN_USER structure.
|
// Get the TOKEN_USER structure.
|
||||||
scoped_array<char> token_user_bytes(new char[token_user_size]);
|
scoped_ptr<char[]> token_user_bytes(new char[token_user_size]);
|
||||||
PTOKEN_USER token_user = reinterpret_cast<PTOKEN_USER>(
|
PTOKEN_USER token_user = reinterpret_cast<PTOKEN_USER>(
|
||||||
token_user_bytes.get());
|
token_user_bytes.get());
|
||||||
memset(token_user, 0, token_user_size);
|
memset(token_user, 0, token_user_size);
|
||||||
@ -137,7 +137,7 @@ bool Win32Filesystem::CreatePrivateFile(const Pathname &filename) {
|
|||||||
GetLengthSid(token_user->User.Sid);
|
GetLengthSid(token_user->User.Sid);
|
||||||
|
|
||||||
// Allocate it.
|
// Allocate it.
|
||||||
scoped_array<char> acl_bytes(new char[acl_size]);
|
scoped_ptr<char[]> acl_bytes(new char[acl_size]);
|
||||||
PACL acl = reinterpret_cast<PACL>(acl_bytes.get());
|
PACL acl = reinterpret_cast<PACL>(acl_bytes.get());
|
||||||
memset(acl, 0, acl_size);
|
memset(acl, 0, acl_size);
|
||||||
if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) {
|
if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) {
|
||||||
@ -440,7 +440,7 @@ bool Win32Filesystem::GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
|
|||||||
Pathname Win32Filesystem::GetCurrentDirectory() {
|
Pathname Win32Filesystem::GetCurrentDirectory() {
|
||||||
Pathname cwd;
|
Pathname cwd;
|
||||||
int path_len = 0;
|
int path_len = 0;
|
||||||
scoped_array<wchar_t> path;
|
scoped_ptr<wchar_t[]> path;
|
||||||
do {
|
do {
|
||||||
int needed = ::GetCurrentDirectory(path_len, path.get());
|
int needed = ::GetCurrentDirectory(path_len, path.get());
|
||||||
if (needed == 0) {
|
if (needed == 0) {
|
||||||
|
@ -160,7 +160,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
|
|||||||
ASSERT(full_key_name != NULL);
|
ASSERT(full_key_name != NULL);
|
||||||
|
|
||||||
DWORD byte_count = 0;
|
DWORD byte_count = 0;
|
||||||
scoped_array<byte> buffer;
|
scoped_ptr<byte[]> buffer;
|
||||||
HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
|
HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
|
||||||
REG_BINARY, buffer.accept(), &byte_count);
|
REG_BINARY, buffer.accept(), &byte_count);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
@ -179,7 +179,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
|
|||||||
ASSERT(full_key_name != NULL);
|
ASSERT(full_key_name != NULL);
|
||||||
|
|
||||||
DWORD byte_count = 0;
|
DWORD byte_count = 0;
|
||||||
scoped_array<byte> buffer;
|
scoped_ptr<byte[]> buffer;
|
||||||
HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
|
HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
|
||||||
REG_BINARY, buffer.accept(), &byte_count);
|
REG_BINARY, buffer.accept(), &byte_count);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
@ -206,7 +206,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
|
|||||||
ASSERT(full_key_name != NULL);
|
ASSERT(full_key_name != NULL);
|
||||||
ASSERT(value != NULL);
|
ASSERT(value != NULL);
|
||||||
|
|
||||||
scoped_array<wchar_t> buffer;
|
scoped_ptr<wchar_t[]> buffer;
|
||||||
HRESULT hr = RegKey::GetValue(full_key_name, value_name, buffer.accept());
|
HRESULT hr = RegKey::GetValue(full_key_name, value_name, buffer.accept());
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
value->assign(buffer.get());
|
value->assign(buffer.get());
|
||||||
|
@ -620,6 +620,9 @@ int Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) {
|
|||||||
*slevel = IPPROTO_TCP;
|
*slevel = IPPROTO_TCP;
|
||||||
*sopt = TCP_NODELAY;
|
*sopt = TCP_NODELAY;
|
||||||
break;
|
break;
|
||||||
|
case OPT_DSCP:
|
||||||
|
LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
|
||||||
|
return -1;
|
||||||
default:
|
default:
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -396,7 +396,7 @@ CallClient::CallClient(buzz::XmppClient* xmpp_client,
|
|||||||
transport_protocol_(cricket::ICEPROTO_HYBRID),
|
transport_protocol_(cricket::ICEPROTO_HYBRID),
|
||||||
sdes_policy_(cricket::SEC_DISABLED),
|
sdes_policy_(cricket::SEC_DISABLED),
|
||||||
dtls_policy_(cricket::SEC_DISABLED),
|
dtls_policy_(cricket::SEC_DISABLED),
|
||||||
ssl_identity_(NULL),
|
ssl_identity_(),
|
||||||
show_roster_messages_(false) {
|
show_roster_messages_(false) {
|
||||||
xmpp_client_->SignalStateChange.connect(this, &CallClient::OnStateChange);
|
xmpp_client_->SignalStateChange.connect(this, &CallClient::OnStateChange);
|
||||||
my_status_.set_caps_node(caps_node);
|
my_status_.set_caps_node(caps_node);
|
||||||
|
@ -38,10 +38,10 @@
|
|||||||
|
|
||||||
ChatApp::ChatApp(buzz::XmppClient* xmpp_client, talk_base::Thread* main_thread)
|
ChatApp::ChatApp(buzz::XmppClient* xmpp_client, talk_base::Thread* main_thread)
|
||||||
: xmpp_client_(xmpp_client),
|
: xmpp_client_(xmpp_client),
|
||||||
presence_out_task_(NULL),
|
presence_out_task_(),
|
||||||
presence_receive_task_(NULL),
|
presence_receive_task_(),
|
||||||
message_send_task_(NULL),
|
message_send_task_(),
|
||||||
message_received_task_(NULL),
|
message_received_task_(),
|
||||||
console_task_(new buzz::ConsoleTask(main_thread)),
|
console_task_(new buzz::ConsoleTask(main_thread)),
|
||||||
ui_state_(STATE_BASE) {
|
ui_state_(STATE_BASE) {
|
||||||
xmpp_client_->SignalStateChange.connect(this, &ChatApp::OnStateChange);
|
xmpp_client_->SignalStateChange.connect(this, &ChatApp::OnStateChange);
|
||||||
|
@ -110,7 +110,7 @@ class GtkMainWnd : public MainWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
talk_base::scoped_array<uint8> image_;
|
talk_base::scoped_ptr<uint8[]> image_;
|
||||||
int width_;
|
int width_;
|
||||||
int height_;
|
int height_;
|
||||||
GtkMainWnd* main_wnd_;
|
GtkMainWnd* main_wnd_;
|
||||||
|
@ -147,7 +147,7 @@ class MainWnd : public MainWindow {
|
|||||||
|
|
||||||
HWND wnd_;
|
HWND wnd_;
|
||||||
BITMAPINFO bmi_;
|
BITMAPINFO bmi_;
|
||||||
talk_base::scoped_array<uint8> image_;
|
talk_base::scoped_ptr<uint8[]> image_;
|
||||||
CRITICAL_SECTION buffer_lock_;
|
CRITICAL_SECTION buffer_lock_;
|
||||||
talk_base::scoped_refptr<webrtc::VideoTrackInterface> rendered_track_;
|
talk_base::scoped_refptr<webrtc::VideoTrackInterface> rendered_track_;
|
||||||
};
|
};
|
||||||
|
@ -51,8 +51,8 @@ void CpuInfo::MaskCpuFlagsForTest(int enable_flags) {
|
|||||||
bool IsCoreIOrBetter() {
|
bool IsCoreIOrBetter() {
|
||||||
#if !defined(DISABLE_YUV) && (defined(__i386__) || defined(__x86_64__) || \
|
#if !defined(DISABLE_YUV) && (defined(__i386__) || defined(__x86_64__) || \
|
||||||
defined(_M_IX86) || defined(_M_X64))
|
defined(_M_IX86) || defined(_M_X64))
|
||||||
int cpu_info[4];
|
uint32 cpu_info[4];
|
||||||
libyuv::CpuId(cpu_info, 0); // Function 0: Vendor ID
|
libyuv::CpuId(0, 0, &cpu_info[0]); // Function 0: Vendor ID
|
||||||
if (cpu_info[1] == 0x756e6547 && cpu_info[3] == 0x49656e69 &&
|
if (cpu_info[1] == 0x756e6547 && cpu_info[3] == 0x49656e69 &&
|
||||||
cpu_info[2] == 0x6c65746e) { // GenuineIntel
|
cpu_info[2] == 0x6c65746e) { // GenuineIntel
|
||||||
// Detect CPU Family and Model
|
// Detect CPU Family and Model
|
||||||
@ -62,7 +62,7 @@ bool IsCoreIOrBetter() {
|
|||||||
// 13:12 - Processor Type
|
// 13:12 - Processor Type
|
||||||
// 19:16 - Extended Model
|
// 19:16 - Extended Model
|
||||||
// 27:20 - Extended Family
|
// 27:20 - Extended Family
|
||||||
libyuv::CpuId(cpu_info, 1); // Function 1: Family and Model
|
libyuv::CpuId(1, 0, &cpu_info[0]); // Function 1: Family and Model
|
||||||
int family = ((cpu_info[0] >> 8) & 0x0f) | ((cpu_info[0] >> 16) & 0xff0);
|
int family = ((cpu_info[0] >> 8) & 0x0f) | ((cpu_info[0] >> 16) & 0xff0);
|
||||||
int model = ((cpu_info[0] >> 4) & 0x0f) | ((cpu_info[0] >> 12) & 0xf0);
|
int model = ((cpu_info[0] >> 4) & 0x0f) | ((cpu_info[0] >> 12) & 0xf0);
|
||||||
// CpuFamily | CpuModel | Name
|
// CpuFamily | CpuModel | Name
|
||||||
|
@ -101,7 +101,7 @@ class FakeVideoCapturer : public cricket::VideoCapturer {
|
|||||||
frame.time_stamp = initial_unix_timestamp_ + next_timestamp_;
|
frame.time_stamp = initial_unix_timestamp_ + next_timestamp_;
|
||||||
next_timestamp_ += 33333333; // 30 fps
|
next_timestamp_ += 33333333; // 30 fps
|
||||||
|
|
||||||
talk_base::scoped_array<char> data(new char[size]);
|
talk_base::scoped_ptr<char[]> data(new char[size]);
|
||||||
frame.data = data.get();
|
frame.data = data.get();
|
||||||
// Copy something non-zero into the buffer so Validate wont complain that
|
// Copy something non-zero into the buffer so Validate wont complain that
|
||||||
// the frame is all duplicate.
|
// the frame is all duplicate.
|
||||||
|
@ -162,29 +162,51 @@ struct AudioOptions {
|
|||||||
void SetAll(const AudioOptions& change) {
|
void SetAll(const AudioOptions& change) {
|
||||||
echo_cancellation.SetFrom(change.echo_cancellation);
|
echo_cancellation.SetFrom(change.echo_cancellation);
|
||||||
auto_gain_control.SetFrom(change.auto_gain_control);
|
auto_gain_control.SetFrom(change.auto_gain_control);
|
||||||
|
rx_auto_gain_control.SetFrom(change.rx_auto_gain_control);
|
||||||
noise_suppression.SetFrom(change.noise_suppression);
|
noise_suppression.SetFrom(change.noise_suppression);
|
||||||
highpass_filter.SetFrom(change.highpass_filter);
|
highpass_filter.SetFrom(change.highpass_filter);
|
||||||
stereo_swapping.SetFrom(change.stereo_swapping);
|
stereo_swapping.SetFrom(change.stereo_swapping);
|
||||||
typing_detection.SetFrom(change.typing_detection);
|
typing_detection.SetFrom(change.typing_detection);
|
||||||
|
aecm_generate_comfort_noise.SetFrom(change.aecm_generate_comfort_noise);
|
||||||
conference_mode.SetFrom(change.conference_mode);
|
conference_mode.SetFrom(change.conference_mode);
|
||||||
adjust_agc_delta.SetFrom(change.adjust_agc_delta);
|
adjust_agc_delta.SetFrom(change.adjust_agc_delta);
|
||||||
experimental_agc.SetFrom(change.experimental_agc);
|
experimental_agc.SetFrom(change.experimental_agc);
|
||||||
experimental_aec.SetFrom(change.experimental_aec);
|
experimental_aec.SetFrom(change.experimental_aec);
|
||||||
aec_dump.SetFrom(change.aec_dump);
|
aec_dump.SetFrom(change.aec_dump);
|
||||||
|
tx_agc_target_dbov.SetFrom(change.tx_agc_target_dbov);
|
||||||
|
tx_agc_digital_compression_gain.SetFrom(
|
||||||
|
change.tx_agc_digital_compression_gain);
|
||||||
|
tx_agc_limiter.SetFrom(change.tx_agc_limiter);
|
||||||
|
rx_agc_target_dbov.SetFrom(change.rx_agc_target_dbov);
|
||||||
|
rx_agc_digital_compression_gain.SetFrom(
|
||||||
|
change.rx_agc_digital_compression_gain);
|
||||||
|
rx_agc_limiter.SetFrom(change.rx_agc_limiter);
|
||||||
|
recording_sample_rate.SetFrom(change.recording_sample_rate);
|
||||||
|
playout_sample_rate.SetFrom(change.playout_sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const AudioOptions& o) const {
|
bool operator==(const AudioOptions& o) const {
|
||||||
return echo_cancellation == o.echo_cancellation &&
|
return echo_cancellation == o.echo_cancellation &&
|
||||||
auto_gain_control == o.auto_gain_control &&
|
auto_gain_control == o.auto_gain_control &&
|
||||||
|
rx_auto_gain_control == o.rx_auto_gain_control &&
|
||||||
noise_suppression == o.noise_suppression &&
|
noise_suppression == o.noise_suppression &&
|
||||||
highpass_filter == o.highpass_filter &&
|
highpass_filter == o.highpass_filter &&
|
||||||
stereo_swapping == o.stereo_swapping &&
|
stereo_swapping == o.stereo_swapping &&
|
||||||
typing_detection == o.typing_detection &&
|
typing_detection == o.typing_detection &&
|
||||||
|
aecm_generate_comfort_noise == o.aecm_generate_comfort_noise &&
|
||||||
conference_mode == o.conference_mode &&
|
conference_mode == o.conference_mode &&
|
||||||
experimental_agc == o.experimental_agc &&
|
experimental_agc == o.experimental_agc &&
|
||||||
experimental_aec == o.experimental_aec &&
|
experimental_aec == o.experimental_aec &&
|
||||||
adjust_agc_delta == o.adjust_agc_delta &&
|
adjust_agc_delta == o.adjust_agc_delta &&
|
||||||
aec_dump == o.aec_dump;
|
aec_dump == o.aec_dump &&
|
||||||
|
tx_agc_target_dbov == o.tx_agc_target_dbov &&
|
||||||
|
tx_agc_digital_compression_gain == o.tx_agc_digital_compression_gain &&
|
||||||
|
tx_agc_limiter == o.tx_agc_limiter &&
|
||||||
|
rx_agc_target_dbov == o.rx_agc_target_dbov &&
|
||||||
|
rx_agc_digital_compression_gain == o.rx_agc_digital_compression_gain &&
|
||||||
|
rx_agc_limiter == o.rx_agc_limiter &&
|
||||||
|
recording_sample_rate == o.recording_sample_rate &&
|
||||||
|
playout_sample_rate == o.playout_sample_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() const {
|
std::string ToString() const {
|
||||||
@ -192,15 +214,27 @@ struct AudioOptions {
|
|||||||
ost << "AudioOptions {";
|
ost << "AudioOptions {";
|
||||||
ost << ToStringIfSet("aec", echo_cancellation);
|
ost << ToStringIfSet("aec", echo_cancellation);
|
||||||
ost << ToStringIfSet("agc", auto_gain_control);
|
ost << ToStringIfSet("agc", auto_gain_control);
|
||||||
|
ost << ToStringIfSet("rx_agc", rx_auto_gain_control);
|
||||||
ost << ToStringIfSet("ns", noise_suppression);
|
ost << ToStringIfSet("ns", noise_suppression);
|
||||||
ost << ToStringIfSet("hf", highpass_filter);
|
ost << ToStringIfSet("hf", highpass_filter);
|
||||||
ost << ToStringIfSet("swap", stereo_swapping);
|
ost << ToStringIfSet("swap", stereo_swapping);
|
||||||
ost << ToStringIfSet("typing", typing_detection);
|
ost << ToStringIfSet("typing", typing_detection);
|
||||||
|
ost << ToStringIfSet("comfort_noise", aecm_generate_comfort_noise);
|
||||||
ost << ToStringIfSet("conference", conference_mode);
|
ost << ToStringIfSet("conference", conference_mode);
|
||||||
ost << ToStringIfSet("agc_delta", adjust_agc_delta);
|
ost << ToStringIfSet("agc_delta", adjust_agc_delta);
|
||||||
ost << ToStringIfSet("experimental_agc", experimental_agc);
|
ost << ToStringIfSet("experimental_agc", experimental_agc);
|
||||||
ost << ToStringIfSet("experimental_aec", experimental_aec);
|
ost << ToStringIfSet("experimental_aec", experimental_aec);
|
||||||
ost << ToStringIfSet("aec_dump", aec_dump);
|
ost << ToStringIfSet("aec_dump", aec_dump);
|
||||||
|
ost << ToStringIfSet("tx_agc_target_dbov", tx_agc_target_dbov);
|
||||||
|
ost << ToStringIfSet("tx_agc_digital_compression_gain",
|
||||||
|
tx_agc_digital_compression_gain);
|
||||||
|
ost << ToStringIfSet("tx_agc_limiter", tx_agc_limiter);
|
||||||
|
ost << ToStringIfSet("rx_agc_target_dbov", rx_agc_target_dbov);
|
||||||
|
ost << ToStringIfSet("rx_agc_digital_compression_gain",
|
||||||
|
rx_agc_digital_compression_gain);
|
||||||
|
ost << ToStringIfSet("rx_agc_limiter", rx_agc_limiter);
|
||||||
|
ost << ToStringIfSet("recording_sample_rate", recording_sample_rate);
|
||||||
|
ost << ToStringIfSet("playout_sample_rate", playout_sample_rate);
|
||||||
ost << "}";
|
ost << "}";
|
||||||
return ost.str();
|
return ost.str();
|
||||||
}
|
}
|
||||||
@ -210,6 +244,8 @@ struct AudioOptions {
|
|||||||
Settable<bool> echo_cancellation;
|
Settable<bool> echo_cancellation;
|
||||||
// Audio processing to adjust the sensitivity of the local mic dynamically.
|
// Audio processing to adjust the sensitivity of the local mic dynamically.
|
||||||
Settable<bool> auto_gain_control;
|
Settable<bool> auto_gain_control;
|
||||||
|
// Audio processing to apply gain to the remote audio.
|
||||||
|
Settable<bool> rx_auto_gain_control;
|
||||||
// Audio processing to filter out background noise.
|
// Audio processing to filter out background noise.
|
||||||
Settable<bool> noise_suppression;
|
Settable<bool> noise_suppression;
|
||||||
// Audio processing to remove background noise of lower frequencies.
|
// Audio processing to remove background noise of lower frequencies.
|
||||||
@ -218,11 +254,21 @@ struct AudioOptions {
|
|||||||
Settable<bool> stereo_swapping;
|
Settable<bool> stereo_swapping;
|
||||||
// Audio processing to detect typing.
|
// Audio processing to detect typing.
|
||||||
Settable<bool> typing_detection;
|
Settable<bool> typing_detection;
|
||||||
|
Settable<bool> aecm_generate_comfort_noise;
|
||||||
Settable<bool> conference_mode;
|
Settable<bool> conference_mode;
|
||||||
Settable<int> adjust_agc_delta;
|
Settable<int> adjust_agc_delta;
|
||||||
Settable<bool> experimental_agc;
|
Settable<bool> experimental_agc;
|
||||||
Settable<bool> experimental_aec;
|
Settable<bool> experimental_aec;
|
||||||
Settable<bool> aec_dump;
|
Settable<bool> aec_dump;
|
||||||
|
// Note that tx_agc_* only applies to non-experimental AGC.
|
||||||
|
Settable<uint16> tx_agc_target_dbov;
|
||||||
|
Settable<uint16> tx_agc_digital_compression_gain;
|
||||||
|
Settable<bool> tx_agc_limiter;
|
||||||
|
Settable<uint16> rx_agc_target_dbov;
|
||||||
|
Settable<uint16> rx_agc_digital_compression_gain;
|
||||||
|
Settable<bool> rx_agc_limiter;
|
||||||
|
Settable<uint32> recording_sample_rate;
|
||||||
|
Settable<uint32> playout_sample_rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Options that can be applied to a VideoMediaChannel or a VideoMediaEngine.
|
// Options that can be applied to a VideoMediaChannel or a VideoMediaEngine.
|
||||||
@ -244,12 +290,13 @@ struct VideoOptions {
|
|||||||
video_adapt_third.SetFrom(change.video_adapt_third);
|
video_adapt_third.SetFrom(change.video_adapt_third);
|
||||||
video_noise_reduction.SetFrom(change.video_noise_reduction);
|
video_noise_reduction.SetFrom(change.video_noise_reduction);
|
||||||
video_three_layers.SetFrom(change.video_three_layers);
|
video_three_layers.SetFrom(change.video_three_layers);
|
||||||
video_enable_camera_list.SetFrom(change.video_enable_camera_list);
|
|
||||||
video_one_layer_screencast.SetFrom(change.video_one_layer_screencast);
|
video_one_layer_screencast.SetFrom(change.video_one_layer_screencast);
|
||||||
video_high_bitrate.SetFrom(change.video_high_bitrate);
|
video_high_bitrate.SetFrom(change.video_high_bitrate);
|
||||||
video_watermark.SetFrom(change.video_watermark);
|
video_watermark.SetFrom(change.video_watermark);
|
||||||
video_temporal_layer_screencast.SetFrom(
|
video_temporal_layer_screencast.SetFrom(
|
||||||
change.video_temporal_layer_screencast);
|
change.video_temporal_layer_screencast);
|
||||||
|
video_temporal_layer_realtime.SetFrom(
|
||||||
|
change.video_temporal_layer_realtime);
|
||||||
video_leaky_bucket.SetFrom(change.video_leaky_bucket);
|
video_leaky_bucket.SetFrom(change.video_leaky_bucket);
|
||||||
cpu_overuse_detection.SetFrom(change.cpu_overuse_detection);
|
cpu_overuse_detection.SetFrom(change.cpu_overuse_detection);
|
||||||
conference_mode.SetFrom(change.conference_mode);
|
conference_mode.SetFrom(change.conference_mode);
|
||||||
@ -269,11 +316,11 @@ struct VideoOptions {
|
|||||||
video_adapt_third == o.video_adapt_third &&
|
video_adapt_third == o.video_adapt_third &&
|
||||||
video_noise_reduction == o.video_noise_reduction &&
|
video_noise_reduction == o.video_noise_reduction &&
|
||||||
video_three_layers == o.video_three_layers &&
|
video_three_layers == o.video_three_layers &&
|
||||||
video_enable_camera_list == o.video_enable_camera_list &&
|
|
||||||
video_one_layer_screencast == o.video_one_layer_screencast &&
|
video_one_layer_screencast == o.video_one_layer_screencast &&
|
||||||
video_high_bitrate == o.video_high_bitrate &&
|
video_high_bitrate == o.video_high_bitrate &&
|
||||||
video_watermark == o.video_watermark &&
|
video_watermark == o.video_watermark &&
|
||||||
video_temporal_layer_screencast == o.video_temporal_layer_screencast &&
|
video_temporal_layer_screencast == o.video_temporal_layer_screencast &&
|
||||||
|
video_temporal_layer_realtime == o.video_temporal_layer_realtime &&
|
||||||
video_leaky_bucket == o.video_leaky_bucket &&
|
video_leaky_bucket == o.video_leaky_bucket &&
|
||||||
cpu_overuse_detection == o.cpu_overuse_detection &&
|
cpu_overuse_detection == o.cpu_overuse_detection &&
|
||||||
conference_mode == o.conference_mode &&
|
conference_mode == o.conference_mode &&
|
||||||
@ -295,12 +342,13 @@ struct VideoOptions {
|
|||||||
ost << ToStringIfSet("video adapt third", video_adapt_third);
|
ost << ToStringIfSet("video adapt third", video_adapt_third);
|
||||||
ost << ToStringIfSet("noise reduction", video_noise_reduction);
|
ost << ToStringIfSet("noise reduction", video_noise_reduction);
|
||||||
ost << ToStringIfSet("3 layers", video_three_layers);
|
ost << ToStringIfSet("3 layers", video_three_layers);
|
||||||
ost << ToStringIfSet("camera list", video_enable_camera_list);
|
|
||||||
ost << ToStringIfSet("1 layer screencast", video_one_layer_screencast);
|
ost << ToStringIfSet("1 layer screencast", video_one_layer_screencast);
|
||||||
ost << ToStringIfSet("high bitrate", video_high_bitrate);
|
ost << ToStringIfSet("high bitrate", video_high_bitrate);
|
||||||
ost << ToStringIfSet("watermark", video_watermark);
|
ost << ToStringIfSet("watermark", video_watermark);
|
||||||
ost << ToStringIfSet("video temporal layer screencast",
|
ost << ToStringIfSet("video temporal layer screencast",
|
||||||
video_temporal_layer_screencast);
|
video_temporal_layer_screencast);
|
||||||
|
ost << ToStringIfSet("video temporal layer realtime",
|
||||||
|
video_temporal_layer_realtime);
|
||||||
ost << ToStringIfSet("leaky bucket", video_leaky_bucket);
|
ost << ToStringIfSet("leaky bucket", video_leaky_bucket);
|
||||||
ost << ToStringIfSet("cpu overuse detection", cpu_overuse_detection);
|
ost << ToStringIfSet("cpu overuse detection", cpu_overuse_detection);
|
||||||
ost << ToStringIfSet("conference mode", conference_mode);
|
ost << ToStringIfSet("conference mode", conference_mode);
|
||||||
@ -326,8 +374,6 @@ struct VideoOptions {
|
|||||||
Settable<bool> video_noise_reduction;
|
Settable<bool> video_noise_reduction;
|
||||||
// Experimental: Enable multi layer?
|
// Experimental: Enable multi layer?
|
||||||
Settable<bool> video_three_layers;
|
Settable<bool> video_three_layers;
|
||||||
// Experimental: Enable camera list?
|
|
||||||
Settable<bool> video_enable_camera_list;
|
|
||||||
// Experimental: Enable one layer screencast?
|
// Experimental: Enable one layer screencast?
|
||||||
Settable<bool> video_one_layer_screencast;
|
Settable<bool> video_one_layer_screencast;
|
||||||
// Experimental: Enable WebRtc higher bitrate?
|
// Experimental: Enable WebRtc higher bitrate?
|
||||||
@ -336,6 +382,8 @@ struct VideoOptions {
|
|||||||
Settable<bool> video_watermark;
|
Settable<bool> video_watermark;
|
||||||
// Experimental: Enable WebRTC layered screencast.
|
// Experimental: Enable WebRTC layered screencast.
|
||||||
Settable<bool> video_temporal_layer_screencast;
|
Settable<bool> video_temporal_layer_screencast;
|
||||||
|
// Experimental: Enable WebRTC temporal layer strategy for realtime video.
|
||||||
|
Settable<bool> video_temporal_layer_realtime;
|
||||||
// Enable WebRTC leaky bucket when sending media packets.
|
// Enable WebRTC leaky bucket when sending media packets.
|
||||||
Settable<bool> video_leaky_bucket;
|
Settable<bool> video_leaky_bucket;
|
||||||
// Enable WebRTC Cpu Overuse Detection, which is a new version of the CPU
|
// Enable WebRTC Cpu Overuse Detection, which is a new version of the CPU
|
||||||
@ -513,15 +561,68 @@ enum SendFlags {
|
|||||||
SEND_MICROPHONE
|
SEND_MICROPHONE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VoiceSenderInfo {
|
// The stats information is structured as follows:
|
||||||
VoiceSenderInfo()
|
// Media are represented by either MediaSenderInfo or MediaReceiverInfo.
|
||||||
|
// Media contains a vector of SSRC infos that are exclusively used by this
|
||||||
|
// media. (SSRCs shared between media streams can't be represented.)
|
||||||
|
|
||||||
|
// Information about an SSRC.
|
||||||
|
// This data may be locally recorded, or received in an RTCP SR or RR.
|
||||||
|
struct SsrcSenderInfo {
|
||||||
|
SsrcSenderInfo()
|
||||||
: ssrc(0),
|
: ssrc(0),
|
||||||
bytes_sent(0),
|
timestamp(0) {
|
||||||
|
}
|
||||||
|
uint32 ssrc;
|
||||||
|
double timestamp; // NTP timestamp, represented as seconds since epoch.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SsrcReceiverInfo {
|
||||||
|
SsrcReceiverInfo()
|
||||||
|
: ssrc(0),
|
||||||
|
timestamp(0) {
|
||||||
|
}
|
||||||
|
uint32 ssrc;
|
||||||
|
double timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MediaSenderInfo {
|
||||||
|
MediaSenderInfo()
|
||||||
|
: bytes_sent(0),
|
||||||
packets_sent(0),
|
packets_sent(0),
|
||||||
packets_lost(0),
|
packets_lost(0),
|
||||||
fraction_lost(0.0),
|
fraction_lost(0.0),
|
||||||
|
rtt_ms(0) {
|
||||||
|
}
|
||||||
|
int64 bytes_sent;
|
||||||
|
int packets_sent;
|
||||||
|
int packets_lost;
|
||||||
|
float fraction_lost;
|
||||||
|
int rtt_ms;
|
||||||
|
std::string codec_name;
|
||||||
|
std::vector<SsrcSenderInfo> local_stats;
|
||||||
|
std::vector<SsrcReceiverInfo> remote_stats;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MediaReceiverInfo {
|
||||||
|
MediaReceiverInfo()
|
||||||
|
: bytes_rcvd(0),
|
||||||
|
packets_rcvd(0),
|
||||||
|
packets_lost(0),
|
||||||
|
fraction_lost(0.0) {
|
||||||
|
}
|
||||||
|
int64 bytes_rcvd;
|
||||||
|
int packets_rcvd;
|
||||||
|
int packets_lost;
|
||||||
|
float fraction_lost;
|
||||||
|
std::vector<SsrcReceiverInfo> local_stats;
|
||||||
|
std::vector<SsrcSenderInfo> remote_stats;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VoiceSenderInfo : public MediaSenderInfo {
|
||||||
|
VoiceSenderInfo()
|
||||||
|
: ssrc(0),
|
||||||
ext_seqnum(0),
|
ext_seqnum(0),
|
||||||
rtt_ms(0),
|
|
||||||
jitter_ms(0),
|
jitter_ms(0),
|
||||||
audio_level(0),
|
audio_level(0),
|
||||||
aec_quality_min(0.0),
|
aec_quality_min(0.0),
|
||||||
@ -533,13 +634,7 @@ struct VoiceSenderInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32 ssrc;
|
uint32 ssrc;
|
||||||
std::string codec_name;
|
|
||||||
int64 bytes_sent;
|
|
||||||
int packets_sent;
|
|
||||||
int packets_lost;
|
|
||||||
float fraction_lost;
|
|
||||||
int ext_seqnum;
|
int ext_seqnum;
|
||||||
int rtt_ms;
|
|
||||||
int jitter_ms;
|
int jitter_ms;
|
||||||
int audio_level;
|
int audio_level;
|
||||||
float aec_quality_min;
|
float aec_quality_min;
|
||||||
@ -550,13 +645,9 @@ struct VoiceSenderInfo {
|
|||||||
bool typing_noise_detected;
|
bool typing_noise_detected;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VoiceReceiverInfo {
|
struct VoiceReceiverInfo : public MediaReceiverInfo {
|
||||||
VoiceReceiverInfo()
|
VoiceReceiverInfo()
|
||||||
: ssrc(0),
|
: ssrc(0),
|
||||||
bytes_rcvd(0),
|
|
||||||
packets_rcvd(0),
|
|
||||||
packets_lost(0),
|
|
||||||
fraction_lost(0.0),
|
|
||||||
ext_seqnum(0),
|
ext_seqnum(0),
|
||||||
jitter_ms(0),
|
jitter_ms(0),
|
||||||
jitter_buffer_ms(0),
|
jitter_buffer_ms(0),
|
||||||
@ -567,10 +658,6 @@ struct VoiceReceiverInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32 ssrc;
|
uint32 ssrc;
|
||||||
int64 bytes_rcvd;
|
|
||||||
int packets_rcvd;
|
|
||||||
int packets_lost;
|
|
||||||
float fraction_lost;
|
|
||||||
int ext_seqnum;
|
int ext_seqnum;
|
||||||
int jitter_ms;
|
int jitter_ms;
|
||||||
int jitter_buffer_ms;
|
int jitter_buffer_ms;
|
||||||
@ -581,16 +668,11 @@ struct VoiceReceiverInfo {
|
|||||||
float expand_rate;
|
float expand_rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VideoSenderInfo {
|
struct VideoSenderInfo : public MediaSenderInfo {
|
||||||
VideoSenderInfo()
|
VideoSenderInfo()
|
||||||
: bytes_sent(0),
|
: packets_cached(0),
|
||||||
packets_sent(0),
|
|
||||||
packets_cached(0),
|
|
||||||
packets_lost(0),
|
|
||||||
fraction_lost(0.0),
|
|
||||||
firs_rcvd(0),
|
firs_rcvd(0),
|
||||||
nacks_rcvd(0),
|
nacks_rcvd(0),
|
||||||
rtt_ms(0),
|
|
||||||
frame_width(0),
|
frame_width(0),
|
||||||
frame_height(0),
|
frame_height(0),
|
||||||
framerate_input(0),
|
framerate_input(0),
|
||||||
@ -602,15 +684,9 @@ struct VideoSenderInfo {
|
|||||||
|
|
||||||
std::vector<uint32> ssrcs;
|
std::vector<uint32> ssrcs;
|
||||||
std::vector<SsrcGroup> ssrc_groups;
|
std::vector<SsrcGroup> ssrc_groups;
|
||||||
std::string codec_name;
|
|
||||||
int64 bytes_sent;
|
|
||||||
int packets_sent;
|
|
||||||
int packets_cached;
|
int packets_cached;
|
||||||
int packets_lost;
|
|
||||||
float fraction_lost;
|
|
||||||
int firs_rcvd;
|
int firs_rcvd;
|
||||||
int nacks_rcvd;
|
int nacks_rcvd;
|
||||||
int rtt_ms;
|
|
||||||
int frame_width;
|
int frame_width;
|
||||||
int frame_height;
|
int frame_height;
|
||||||
int framerate_input;
|
int framerate_input;
|
||||||
@ -620,13 +696,9 @@ struct VideoSenderInfo {
|
|||||||
int adapt_reason;
|
int adapt_reason;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VideoReceiverInfo {
|
struct VideoReceiverInfo : public MediaReceiverInfo {
|
||||||
VideoReceiverInfo()
|
VideoReceiverInfo()
|
||||||
: bytes_rcvd(0),
|
: packets_concealed(0),
|
||||||
packets_rcvd(0),
|
|
||||||
packets_lost(0),
|
|
||||||
packets_concealed(0),
|
|
||||||
fraction_lost(0.0),
|
|
||||||
firs_sent(0),
|
firs_sent(0),
|
||||||
nacks_sent(0),
|
nacks_sent(0),
|
||||||
frame_width(0),
|
frame_width(0),
|
||||||
@ -635,17 +707,19 @@ struct VideoReceiverInfo {
|
|||||||
framerate_decoded(0),
|
framerate_decoded(0),
|
||||||
framerate_output(0),
|
framerate_output(0),
|
||||||
framerate_render_input(0),
|
framerate_render_input(0),
|
||||||
framerate_render_output(0) {
|
framerate_render_output(0),
|
||||||
|
decode_ms(0),
|
||||||
|
max_decode_ms(0),
|
||||||
|
jitter_buffer_ms(0),
|
||||||
|
min_playout_delay_ms(0),
|
||||||
|
render_delay_ms(0),
|
||||||
|
target_delay_ms(0),
|
||||||
|
current_delay_ms(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32> ssrcs;
|
std::vector<uint32> ssrcs;
|
||||||
std::vector<SsrcGroup> ssrc_groups;
|
std::vector<SsrcGroup> ssrc_groups;
|
||||||
int64 bytes_rcvd;
|
|
||||||
// vector<int> layer_bytes_rcvd;
|
|
||||||
int packets_rcvd;
|
|
||||||
int packets_lost;
|
|
||||||
int packets_concealed;
|
int packets_concealed;
|
||||||
float fraction_lost;
|
|
||||||
int firs_sent;
|
int firs_sent;
|
||||||
int nacks_sent;
|
int nacks_sent;
|
||||||
int frame_width;
|
int frame_width;
|
||||||
@ -657,31 +731,42 @@ struct VideoReceiverInfo {
|
|||||||
int framerate_render_input;
|
int framerate_render_input;
|
||||||
// Framerate that the renderer reports.
|
// Framerate that the renderer reports.
|
||||||
int framerate_render_output;
|
int framerate_render_output;
|
||||||
|
|
||||||
|
// All stats below are gathered per-VideoReceiver, but some will be correlated
|
||||||
|
// across MediaStreamTracks. NOTE(hta): when sinking stats into per-SSRC
|
||||||
|
// structures, reflect this in the new layout.
|
||||||
|
|
||||||
|
// Current frame decode latency.
|
||||||
|
int decode_ms;
|
||||||
|
// Maximum observed frame decode latency.
|
||||||
|
int max_decode_ms;
|
||||||
|
// Jitter (network-related) latency.
|
||||||
|
int jitter_buffer_ms;
|
||||||
|
// Requested minimum playout latency.
|
||||||
|
int min_playout_delay_ms;
|
||||||
|
// Requested latency to account for rendering delay.
|
||||||
|
int render_delay_ms;
|
||||||
|
// Target overall delay: network+decode+render, accounting for
|
||||||
|
// min_playout_delay_ms.
|
||||||
|
int target_delay_ms;
|
||||||
|
// Current overall delay, possibly ramping towards target_delay_ms.
|
||||||
|
int current_delay_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DataSenderInfo {
|
struct DataSenderInfo : public MediaSenderInfo {
|
||||||
DataSenderInfo()
|
DataSenderInfo()
|
||||||
: ssrc(0),
|
: ssrc(0) {
|
||||||
bytes_sent(0),
|
|
||||||
packets_sent(0) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 ssrc;
|
uint32 ssrc;
|
||||||
std::string codec_name;
|
|
||||||
int64 bytes_sent;
|
|
||||||
int packets_sent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DataReceiverInfo {
|
struct DataReceiverInfo : public MediaReceiverInfo {
|
||||||
DataReceiverInfo()
|
DataReceiverInfo()
|
||||||
: ssrc(0),
|
: ssrc(0) {
|
||||||
bytes_rcvd(0),
|
|
||||||
packets_rcvd(0) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 ssrc;
|
uint32 ssrc;
|
||||||
int64 bytes_rcvd;
|
|
||||||
int packets_rcvd;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BandwidthEstimationInfo {
|
struct BandwidthEstimationInfo {
|
||||||
|
@ -373,7 +373,7 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
|
|||||||
// TODO(fbarchard): Avoid scale and convert if muted.
|
// TODO(fbarchard): Avoid scale and convert if muted.
|
||||||
// Temporary buffer is scoped here so it will persist until i420_frame.Init()
|
// Temporary buffer is scoped here so it will persist until i420_frame.Init()
|
||||||
// makes a copy of the frame, converting to I420.
|
// makes a copy of the frame, converting to I420.
|
||||||
talk_base::scoped_array<uint8> temp_buffer;
|
talk_base::scoped_ptr<uint8[]> temp_buffer;
|
||||||
// YUY2 can be scaled vertically using an ARGB scaler. Aspect ratio is only
|
// YUY2 can be scaled vertically using an ARGB scaler. Aspect ratio is only
|
||||||
// a problem on OSX. OSX always converts webcams to YUY2 or UYVY.
|
// a problem on OSX. OSX always converts webcams to YUY2 or UYVY.
|
||||||
bool can_scale =
|
bool can_scale =
|
||||||
|
@ -153,12 +153,15 @@ void ComputeScale(int frame_width, int frame_height, int fps,
|
|||||||
|
|
||||||
// Compute size to crop video frame to.
|
// Compute size to crop video frame to.
|
||||||
// If cropped_format_* is 0, return the frame_* size as is.
|
// If cropped_format_* is 0, return the frame_* size as is.
|
||||||
void ComputeCrop(int cropped_format_width,
|
void ComputeCrop(int cropped_format_width, int cropped_format_height,
|
||||||
int cropped_format_height,
|
|
||||||
int frame_width, int frame_height,
|
int frame_width, int frame_height,
|
||||||
int pixel_width, int pixel_height,
|
int pixel_width, int pixel_height,
|
||||||
int rotation,
|
int rotation,
|
||||||
int* cropped_width, int* cropped_height) {
|
int* cropped_width, int* cropped_height) {
|
||||||
|
// Transform screen crop to camera space if rotated.
|
||||||
|
if (rotation == 90 || rotation == 270) {
|
||||||
|
std::swap(cropped_format_width, cropped_format_height);
|
||||||
|
}
|
||||||
ASSERT(cropped_format_width >= 0);
|
ASSERT(cropped_format_width >= 0);
|
||||||
ASSERT(cropped_format_height >= 0);
|
ASSERT(cropped_format_height >= 0);
|
||||||
ASSERT(frame_width > 0);
|
ASSERT(frame_width > 0);
|
||||||
@ -182,39 +185,26 @@ void ComputeCrop(int cropped_format_width,
|
|||||||
static_cast<float>(frame_height * pixel_height);
|
static_cast<float>(frame_height * pixel_height);
|
||||||
float crop_aspect = static_cast<float>(cropped_format_width) /
|
float crop_aspect = static_cast<float>(cropped_format_width) /
|
||||||
static_cast<float>(cropped_format_height);
|
static_cast<float>(cropped_format_height);
|
||||||
int new_frame_width = frame_width;
|
|
||||||
int new_frame_height = frame_height;
|
|
||||||
if (rotation == 90 || rotation == 270) {
|
|
||||||
frame_aspect = 1.0f / frame_aspect;
|
|
||||||
new_frame_width = frame_height;
|
|
||||||
new_frame_height = frame_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
// kAspectThresh is the maximum aspect ratio difference that we'll accept
|
// kAspectThresh is the maximum aspect ratio difference that we'll accept
|
||||||
// for cropping. The value 1.33 is based on 4:3 being cropped to 16:9.
|
// for cropping. The value 1.34 allows cropping from 4:3 to 16:9.
|
||||||
// Set to zero to disable cropping entirely.
|
// Set to zero to disable cropping entirely.
|
||||||
// TODO(fbarchard): crop to multiple of 16 width for better performance.
|
// TODO(fbarchard): crop to multiple of 16 width for better performance.
|
||||||
const float kAspectThresh = 16.f / 9.f / (4.f / 3.f) + 0.01f; // 1.33
|
const float kAspectThresh = 1.34f;
|
||||||
// Wide aspect - crop horizontally
|
// Wide aspect - crop horizontally
|
||||||
if (frame_aspect > crop_aspect &&
|
if (frame_aspect > crop_aspect &&
|
||||||
frame_aspect < crop_aspect * kAspectThresh) {
|
frame_aspect < crop_aspect * kAspectThresh) {
|
||||||
// Round width down to multiple of 4 to avoid odd chroma width.
|
// Round width down to multiple of 4 to avoid odd chroma width.
|
||||||
// Width a multiple of 4 allows a half size image to have chroma channel
|
// Width a multiple of 4 allows a half size image to have chroma channel
|
||||||
// that avoids rounding errors. lmi and webrtc have odd width limitations.
|
// that avoids rounding errors.
|
||||||
new_frame_width = static_cast<int>((crop_aspect * frame_height *
|
frame_width = static_cast<int>((crop_aspect * frame_height *
|
||||||
pixel_height) / pixel_width + 0.5f) & ~3;
|
pixel_height) / pixel_width + 0.5f) & ~3;
|
||||||
} else if (crop_aspect > frame_aspect &&
|
} else if (frame_aspect < crop_aspect &&
|
||||||
crop_aspect < frame_aspect * kAspectThresh) {
|
frame_aspect > crop_aspect / kAspectThresh) {
|
||||||
new_frame_height = static_cast<int>((frame_width * pixel_width) /
|
frame_height = static_cast<int>((frame_width * pixel_width) /
|
||||||
(crop_aspect * pixel_height) + 0.5f) & ~1;
|
(crop_aspect * pixel_height) + 0.5f) & ~1;
|
||||||
}
|
}
|
||||||
|
*cropped_width = frame_width;
|
||||||
*cropped_width = new_frame_width;
|
*cropped_height = frame_height;
|
||||||
*cropped_height = new_frame_height;
|
|
||||||
if (rotation == 90 || rotation == 270) {
|
|
||||||
*cropped_width = new_frame_height;
|
|
||||||
*cropped_height = new_frame_width;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the frame size that makes pixels square pixel aspect ratio.
|
// Compute the frame size that makes pixels square pixel aspect ratio.
|
||||||
|
@ -276,6 +276,15 @@ TEST(VideoCommonTest, TestComputeCrop) {
|
|||||||
EXPECT_EQ(640, cropped_width);
|
EXPECT_EQ(640, cropped_width);
|
||||||
EXPECT_EQ(480, cropped_height);
|
EXPECT_EQ(480, cropped_height);
|
||||||
|
|
||||||
|
// Request 9:16 from VGA rotated (portrait). Expect crop.
|
||||||
|
ComputeCrop(360, 640, // Crop size 9:16
|
||||||
|
640, 480, // Frame is 3:4 portrait
|
||||||
|
1, 1, // Normal 1:1 pixels
|
||||||
|
90,
|
||||||
|
&cropped_width, &cropped_height);
|
||||||
|
EXPECT_EQ(640, cropped_width);
|
||||||
|
EXPECT_EQ(360, cropped_height);
|
||||||
|
|
||||||
// Cropped size 0x0. Expect no cropping.
|
// Cropped size 0x0. Expect no cropping.
|
||||||
// This is used when adding multiple capturers
|
// This is used when adding multiple capturers
|
||||||
ComputeCrop(0, 0, // Crop size 0x0
|
ComputeCrop(0, 0, // Crop size 0x0
|
||||||
|
@ -157,7 +157,7 @@ class VideoFrameTest : public testing::Test {
|
|||||||
prefix.c_str(), frame.GetWidth(), frame.GetHeight());
|
prefix.c_str(), frame.GetWidth(), frame.GetHeight());
|
||||||
size_t out_size = cricket::VideoFrame::SizeOf(frame.GetWidth(),
|
size_t out_size = cricket::VideoFrame::SizeOf(frame.GetWidth(),
|
||||||
frame.GetHeight());
|
frame.GetHeight());
|
||||||
talk_base::scoped_array<uint8> out(new uint8[out_size]);
|
talk_base::scoped_ptr<uint8[]> out(new uint8[out_size]);
|
||||||
frame.CopyToBuffer(out.get(), out_size);
|
frame.CopyToBuffer(out.get(), out_size);
|
||||||
return DumpSample(filename, out.get(), out_size);
|
return DumpSample(filename, out.get(), out_size);
|
||||||
}
|
}
|
||||||
@ -514,7 +514,7 @@ class VideoFrameTest : public testing::Test {
|
|||||||
T frame1, frame2;
|
T frame1, frame2;
|
||||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||||
size_t buf_size = kWidth * kHeight * 2;
|
size_t buf_size = kWidth * kHeight * 2;
|
||||||
talk_base::scoped_array<uint8> buf(new uint8[buf_size + kAlignment]);
|
talk_base::scoped_ptr<uint8[]> buf(new uint8[buf_size + kAlignment]);
|
||||||
uint8* y = ALIGNP(buf.get(), kAlignment);
|
uint8* y = ALIGNP(buf.get(), kAlignment);
|
||||||
uint8* u = y + kWidth * kHeight;
|
uint8* u = y + kWidth * kHeight;
|
||||||
uint8* v = u + (kWidth / 2) * kHeight;
|
uint8* v = u + (kWidth / 2) * kHeight;
|
||||||
@ -535,7 +535,7 @@ class VideoFrameTest : public testing::Test {
|
|||||||
T frame1, frame2;
|
T frame1, frame2;
|
||||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||||
size_t buf_size = kWidth * kHeight * 2;
|
size_t buf_size = kWidth * kHeight * 2;
|
||||||
talk_base::scoped_array<uint8> buf(new uint8[buf_size + kAlignment]);
|
talk_base::scoped_ptr<uint8[]> buf(new uint8[buf_size + kAlignment]);
|
||||||
uint8* yuy2 = ALIGNP(buf.get(), kAlignment);
|
uint8* yuy2 = ALIGNP(buf.get(), kAlignment);
|
||||||
EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.GetYPlane(), frame1.GetYPitch(),
|
EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.GetYPlane(), frame1.GetYPitch(),
|
||||||
frame1.GetUPlane(), frame1.GetUPitch(),
|
frame1.GetUPlane(), frame1.GetUPitch(),
|
||||||
@ -552,7 +552,7 @@ class VideoFrameTest : public testing::Test {
|
|||||||
T frame1, frame2;
|
T frame1, frame2;
|
||||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||||
size_t buf_size = kWidth * kHeight * 2;
|
size_t buf_size = kWidth * kHeight * 2;
|
||||||
talk_base::scoped_array<uint8> buf(new uint8[buf_size + kAlignment + 1]);
|
talk_base::scoped_ptr<uint8[]> buf(new uint8[buf_size + kAlignment + 1]);
|
||||||
uint8* yuy2 = ALIGNP(buf.get(), kAlignment) + 1;
|
uint8* yuy2 = ALIGNP(buf.get(), kAlignment) + 1;
|
||||||
EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.GetYPlane(), frame1.GetYPitch(),
|
EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.GetYPlane(), frame1.GetYPitch(),
|
||||||
frame1.GetUPlane(), frame1.GetUPitch(),
|
frame1.GetUPlane(), frame1.GetUPitch(),
|
||||||
@ -718,7 +718,7 @@ class VideoFrameTest : public testing::Test {
|
|||||||
void ConstructRGB565() {
|
void ConstructRGB565() {
|
||||||
T frame1, frame2;
|
T frame1, frame2;
|
||||||
size_t out_size = kWidth * kHeight * 2;
|
size_t out_size = kWidth * kHeight * 2;
|
||||||
talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
|
talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
|
||||||
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
||||||
T frame;
|
T frame;
|
||||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||||
@ -734,7 +734,7 @@ class VideoFrameTest : public testing::Test {
|
|||||||
void ConstructARGB1555() {
|
void ConstructARGB1555() {
|
||||||
T frame1, frame2;
|
T frame1, frame2;
|
||||||
size_t out_size = kWidth * kHeight * 2;
|
size_t out_size = kWidth * kHeight * 2;
|
||||||
talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
|
talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
|
||||||
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
||||||
T frame;
|
T frame;
|
||||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||||
@ -750,7 +750,7 @@ class VideoFrameTest : public testing::Test {
|
|||||||
void ConstructARGB4444() {
|
void ConstructARGB4444() {
|
||||||
T frame1, frame2;
|
T frame1, frame2;
|
||||||
size_t out_size = kWidth * kHeight * 2;
|
size_t out_size = kWidth * kHeight * 2;
|
||||||
talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
|
talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
|
||||||
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
||||||
T frame;
|
T frame;
|
||||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||||
@ -769,7 +769,7 @@ class VideoFrameTest : public testing::Test {
|
|||||||
#define TEST_BYR(NAME, BAYER) \
|
#define TEST_BYR(NAME, BAYER) \
|
||||||
void NAME() { \
|
void NAME() { \
|
||||||
size_t bayer_size = kWidth * kHeight; \
|
size_t bayer_size = kWidth * kHeight; \
|
||||||
talk_base::scoped_array<uint8> bayerbuf(new uint8[ \
|
talk_base::scoped_ptr<uint8[]> bayerbuf(new uint8[ \
|
||||||
bayer_size + kAlignment]); \
|
bayer_size + kAlignment]); \
|
||||||
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment); \
|
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment); \
|
||||||
T frame1, frame2; \
|
T frame1, frame2; \
|
||||||
@ -994,7 +994,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
}
|
}
|
||||||
// Convert back to ARGB.
|
// Convert back to ARGB.
|
||||||
size_t out_size = 4;
|
size_t out_size = 4;
|
||||||
talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
|
talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
|
||||||
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
||||||
|
|
||||||
EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB,
|
EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB,
|
||||||
@ -1031,7 +1031,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
}
|
}
|
||||||
// Convert back to ARGB
|
// Convert back to ARGB
|
||||||
size_t out_size = 10 * 4;
|
size_t out_size = 10 * 4;
|
||||||
talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
|
talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
|
||||||
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
|
||||||
|
|
||||||
EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB,
|
EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB,
|
||||||
@ -1162,7 +1162,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
|
|
||||||
// Allocate a buffer with end page aligned.
|
// Allocate a buffer with end page aligned.
|
||||||
const int kPadToHeapSized = 16 * 1024 * 1024;
|
const int kPadToHeapSized = 16 * 1024 * 1024;
|
||||||
talk_base::scoped_array<uint8> page_buffer(
|
talk_base::scoped_ptr<uint8[]> page_buffer(
|
||||||
new uint8[((data_size + kPadToHeapSized + 4095) & ~4095)]);
|
new uint8[((data_size + kPadToHeapSized + 4095) & ~4095)]);
|
||||||
uint8* data_ptr = page_buffer.get();
|
uint8* data_ptr = page_buffer.get();
|
||||||
if (!data_ptr) {
|
if (!data_ptr) {
|
||||||
@ -1427,7 +1427,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
|
|
||||||
int astride = kWidth * bpp + rowpad;
|
int astride = kWidth * bpp + rowpad;
|
||||||
size_t out_size = astride * kHeight;
|
size_t out_size = astride * kHeight;
|
||||||
talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment + 1]);
|
talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment + 1]);
|
||||||
memset(outbuf.get(), 0, out_size + kAlignment + 1);
|
memset(outbuf.get(), 0, out_size + kAlignment + 1);
|
||||||
uint8 *outtop = ALIGNP(outbuf.get(), kAlignment);
|
uint8 *outtop = ALIGNP(outbuf.get(), kAlignment);
|
||||||
uint8 *out = outtop;
|
uint8 *out = outtop;
|
||||||
@ -1841,7 +1841,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
void ConvertToI422Buffer() {
|
void ConvertToI422Buffer() {
|
||||||
T frame1, frame2;
|
T frame1, frame2;
|
||||||
size_t out_size = kWidth * kHeight * 2;
|
size_t out_size = kWidth * kHeight * 2;
|
||||||
talk_base::scoped_array<uint8> buf(new uint8[out_size + kAlignment]);
|
talk_base::scoped_ptr<uint8[]> buf(new uint8[out_size + kAlignment]);
|
||||||
uint8* y = ALIGNP(buf.get(), kAlignment);
|
uint8* y = ALIGNP(buf.get(), kAlignment);
|
||||||
uint8* u = y + kWidth * kHeight;
|
uint8* u = y + kWidth * kHeight;
|
||||||
uint8* v = u + (kWidth / 2) * kHeight;
|
uint8* v = u + (kWidth / 2) * kHeight;
|
||||||
@ -1865,7 +1865,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
#define TEST_TOBYR(NAME, BAYER) \
|
#define TEST_TOBYR(NAME, BAYER) \
|
||||||
void NAME() { \
|
void NAME() { \
|
||||||
size_t bayer_size = kWidth * kHeight; \
|
size_t bayer_size = kWidth * kHeight; \
|
||||||
talk_base::scoped_array<uint8> bayerbuf(new uint8[ \
|
talk_base::scoped_ptr<uint8[]> bayerbuf(new uint8[ \
|
||||||
bayer_size + kAlignment]); \
|
bayer_size + kAlignment]); \
|
||||||
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment); \
|
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment); \
|
||||||
T frame; \
|
T frame; \
|
||||||
@ -1894,7 +1894,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
} \
|
} \
|
||||||
void NAME##Unaligned() { \
|
void NAME##Unaligned() { \
|
||||||
size_t bayer_size = kWidth * kHeight; \
|
size_t bayer_size = kWidth * kHeight; \
|
||||||
talk_base::scoped_array<uint8> bayerbuf(new uint8[ \
|
talk_base::scoped_ptr<uint8[]> bayerbuf(new uint8[ \
|
||||||
bayer_size + 1 + kAlignment]); \
|
bayer_size + 1 + kAlignment]); \
|
||||||
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment) + 1; \
|
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment) + 1; \
|
||||||
T frame; \
|
T frame; \
|
||||||
@ -1931,7 +1931,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
#define TEST_BYRTORGB(NAME, BAYER) \
|
#define TEST_BYRTORGB(NAME, BAYER) \
|
||||||
void NAME() { \
|
void NAME() { \
|
||||||
size_t bayer_size = kWidth * kHeight; \
|
size_t bayer_size = kWidth * kHeight; \
|
||||||
talk_base::scoped_array<uint8> bayerbuf(new uint8[ \
|
talk_base::scoped_ptr<uint8[]> bayerbuf(new uint8[ \
|
||||||
bayer_size + kAlignment]); \
|
bayer_size + kAlignment]); \
|
||||||
uint8 *bayer1 = ALIGNP(bayerbuf.get(), kAlignment); \
|
uint8 *bayer1 = ALIGNP(bayerbuf.get(), kAlignment); \
|
||||||
for (int i = 0; i < kWidth * kHeight; ++i) { \
|
for (int i = 0; i < kWidth * kHeight; ++i) { \
|
||||||
@ -1947,7 +1947,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
kWidth * 4, \
|
kWidth * 4, \
|
||||||
kWidth, kHeight); \
|
kWidth, kHeight); \
|
||||||
} \
|
} \
|
||||||
talk_base::scoped_array<uint8> bayer2buf(new uint8[ \
|
talk_base::scoped_ptr<uint8[]> bayer2buf(new uint8[ \
|
||||||
bayer_size + kAlignment]); \
|
bayer_size + kAlignment]); \
|
||||||
uint8 *bayer2 = ALIGNP(bayer2buf.get(), kAlignment); \
|
uint8 *bayer2 = ALIGNP(bayer2buf.get(), kAlignment); \
|
||||||
libyuv::ARGBToBayer##BAYER(reinterpret_cast<uint8*>(ms->GetBuffer()), \
|
libyuv::ARGBToBayer##BAYER(reinterpret_cast<uint8*>(ms->GetBuffer()), \
|
||||||
@ -2010,7 +2010,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
ASSERT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_I420, kWidth, kHeight,
|
ASSERT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_I420, kWidth, kHeight,
|
||||||
&frame));
|
&frame));
|
||||||
size_t out_size = kWidth * kHeight * 3 / 2;
|
size_t out_size = kWidth * kHeight * 3 / 2;
|
||||||
talk_base::scoped_array<uint8> out(new uint8[out_size]);
|
talk_base::scoped_ptr<uint8[]> out(new uint8[out_size]);
|
||||||
for (int i = 0; i < repeat_; ++i) {
|
for (int i = 0; i < repeat_; ++i) {
|
||||||
EXPECT_EQ(out_size, frame.CopyToBuffer(out.get(), out_size));
|
EXPECT_EQ(out_size, frame.CopyToBuffer(out.get(), out_size));
|
||||||
}
|
}
|
||||||
@ -2056,7 +2056,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
|||||||
|
|
||||||
void CopyToBuffer1Pixel() {
|
void CopyToBuffer1Pixel() {
|
||||||
size_t out_size = 3;
|
size_t out_size = 3;
|
||||||
talk_base::scoped_array<uint8> out(new uint8[out_size + 1]);
|
talk_base::scoped_ptr<uint8[]> out(new uint8[out_size + 1]);
|
||||||
memset(out.get(), 0xfb, out_size + 1); // Fill buffer
|
memset(out.get(), 0xfb, out_size + 1); // Fill buffer
|
||||||
uint8 pixel[3] = { 1, 2, 3 };
|
uint8 pixel[3] = { 1, 2, 3 };
|
||||||
T frame;
|
T frame;
|
||||||
|
@ -57,7 +57,7 @@ class CarbonVideoRenderer : public VideoRenderer {
|
|||||||
static OSStatus DrawEventHandler(EventHandlerCallRef handler,
|
static OSStatus DrawEventHandler(EventHandlerCallRef handler,
|
||||||
EventRef event,
|
EventRef event,
|
||||||
void* data);
|
void* data);
|
||||||
talk_base::scoped_array<uint8> image_;
|
talk_base::scoped_ptr<uint8[]> image_;
|
||||||
talk_base::CriticalSection image_crit_;
|
talk_base::CriticalSection image_crit_;
|
||||||
int image_width_;
|
int image_width_;
|
||||||
int image_height_;
|
int image_height_;
|
||||||
|
@ -98,7 +98,7 @@ class GdiVideoRenderer::VideoWindow : public talk_base::Win32Window {
|
|||||||
void OnRenderFrame(const VideoFrame* frame);
|
void OnRenderFrame(const VideoFrame* frame);
|
||||||
|
|
||||||
BITMAPINFO bmi_;
|
BITMAPINFO bmi_;
|
||||||
talk_base::scoped_array<uint8> image_;
|
talk_base::scoped_ptr<uint8[]> image_;
|
||||||
talk_base::scoped_ptr<WindowThread> window_thread_;
|
talk_base::scoped_ptr<WindowThread> window_thread_;
|
||||||
// The initial position of the window.
|
// The initial position of the window.
|
||||||
int initial_x_;
|
int initial_x_;
|
||||||
|
@ -56,7 +56,7 @@ class GtkVideoRenderer : public VideoRenderer {
|
|||||||
// Check if the window has been closed.
|
// Check if the window has been closed.
|
||||||
bool IsClosed() const;
|
bool IsClosed() const;
|
||||||
|
|
||||||
talk_base::scoped_array<uint8> image_;
|
talk_base::scoped_ptr<uint8[]> image_;
|
||||||
GtkWidget* window_;
|
GtkWidget* window_;
|
||||||
GtkWidget* draw_area_;
|
GtkWidget* draw_area_;
|
||||||
// The initial position of the window.
|
// The initial position of the window.
|
||||||
|
@ -120,7 +120,7 @@ static bool GetAudioDeviceIDs(bool input,
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t num_devices = propsize / sizeof(AudioDeviceID);
|
size_t num_devices = propsize / sizeof(AudioDeviceID);
|
||||||
talk_base::scoped_array<AudioDeviceID> device_ids(
|
talk_base::scoped_ptr<AudioDeviceID[]> device_ids(
|
||||||
new AudioDeviceID[num_devices]);
|
new AudioDeviceID[num_devices]);
|
||||||
|
|
||||||
err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
|
err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
|
||||||
|
@ -56,7 +56,7 @@ struct socket;
|
|||||||
namespace cricket {
|
namespace cricket {
|
||||||
// The highest stream ID (Sid) that SCTP allows, and the number of streams we
|
// The highest stream ID (Sid) that SCTP allows, and the number of streams we
|
||||||
// tell SCTP we're going to use.
|
// tell SCTP we're going to use.
|
||||||
const uint32 kMaxSctpSid = USHRT_MAX;
|
const uint32 kMaxSctpSid = 1023;
|
||||||
|
|
||||||
// A DataEngine that interacts with usrsctp.
|
// A DataEngine that interacts with usrsctp.
|
||||||
//
|
//
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
// Format defined at
|
// Format defined at
|
||||||
// http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
|
// http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1
|
||||||
|
|
||||||
static const uint8 DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03;
|
static const uint8 DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03;
|
||||||
|
|
||||||
@ -73,16 +73,17 @@ bool ParseDataChannelOpenMessage(
|
|||||||
LOG(LS_WARNING) << "Could not read OPEN message channel type.";
|
LOG(LS_WARNING) << "Could not read OPEN message channel type.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint16 reliability_param;
|
|
||||||
if (!buffer.ReadUInt16(&reliability_param)) {
|
|
||||||
LOG(LS_WARNING) << "Could not read OPEN message reliabilility param.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint16 priority;
|
uint16 priority;
|
||||||
if (!buffer.ReadUInt16(&priority)) {
|
if (!buffer.ReadUInt16(&priority)) {
|
||||||
LOG(LS_WARNING) << "Could not read OPEN message reliabilility prioirty.";
|
LOG(LS_WARNING) << "Could not read OPEN message reliabilility prioirty.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
uint32 reliability_param;
|
||||||
|
if (!buffer.ReadUInt32(&reliability_param)) {
|
||||||
|
LOG(LS_WARNING) << "Could not read OPEN message reliabilility param.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
uint16 label_length;
|
uint16 label_length;
|
||||||
if (!buffer.ReadUInt16(&label_length)) {
|
if (!buffer.ReadUInt16(&label_length)) {
|
||||||
LOG(LS_WARNING) << "Could not read OPEN message label length.";
|
LOG(LS_WARNING) << "Could not read OPEN message label length.";
|
||||||
@ -116,10 +117,11 @@ bool ParseDataChannelOpenMessage(
|
|||||||
case DCOMCT_ORDERED_PARTIAL_RTXS:
|
case DCOMCT_ORDERED_PARTIAL_RTXS:
|
||||||
case DCOMCT_UNORDERED_PARTIAL_RTXS:
|
case DCOMCT_UNORDERED_PARTIAL_RTXS:
|
||||||
config->maxRetransmits = reliability_param;
|
config->maxRetransmits = reliability_param;
|
||||||
|
break;
|
||||||
case DCOMCT_ORDERED_PARTIAL_TIME:
|
case DCOMCT_ORDERED_PARTIAL_TIME:
|
||||||
case DCOMCT_UNORDERED_PARTIAL_TIME:
|
case DCOMCT_UNORDERED_PARTIAL_TIME:
|
||||||
config->maxRetransmitTime = reliability_param;
|
config->maxRetransmitTime = reliability_param;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -130,11 +132,9 @@ bool WriteDataChannelOpenMessage(
|
|||||||
const webrtc::DataChannelInit& config,
|
const webrtc::DataChannelInit& config,
|
||||||
talk_base::Buffer* payload) {
|
talk_base::Buffer* payload) {
|
||||||
// Format defined at
|
// Format defined at
|
||||||
// http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
|
// http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1
|
||||||
// TODO(pthatcher)
|
|
||||||
|
|
||||||
uint8 channel_type = 0;
|
uint8 channel_type = 0;
|
||||||
uint16 reliability_param = 0;
|
uint32 reliability_param = 0;
|
||||||
uint16 priority = 0;
|
uint16 priority = 0;
|
||||||
if (config.ordered) {
|
if (config.ordered) {
|
||||||
if (config.maxRetransmits > -1) {
|
if (config.maxRetransmits > -1) {
|
||||||
@ -163,8 +163,8 @@ bool WriteDataChannelOpenMessage(
|
|||||||
talk_base::ByteBuffer::ORDER_NETWORK);
|
talk_base::ByteBuffer::ORDER_NETWORK);
|
||||||
buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE);
|
buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE);
|
||||||
buffer.WriteUInt8(channel_type);
|
buffer.WriteUInt8(channel_type);
|
||||||
buffer.WriteUInt16(reliability_param);
|
|
||||||
buffer.WriteUInt16(priority);
|
buffer.WriteUInt16(priority);
|
||||||
|
buffer.WriteUInt32(reliability_param);
|
||||||
buffer.WriteUInt16(static_cast<uint16>(label.length()));
|
buffer.WriteUInt16(static_cast<uint16>(label.length()));
|
||||||
buffer.WriteUInt16(static_cast<uint16>(config.protocol.length()));
|
buffer.WriteUInt16(static_cast<uint16>(config.protocol.length()));
|
||||||
buffer.WriteString(label);
|
buffer.WriteString(label);
|
||||||
|
@ -37,7 +37,7 @@ class SctpUtilsTest : public testing::Test {
|
|||||||
const webrtc::DataChannelInit& config) {
|
const webrtc::DataChannelInit& config) {
|
||||||
uint8 message_type;
|
uint8 message_type;
|
||||||
uint8 channel_type;
|
uint8 channel_type;
|
||||||
uint16 reliability;
|
uint32 reliability;
|
||||||
uint16 priority;
|
uint16 priority;
|
||||||
uint16 label_length;
|
uint16 label_length;
|
||||||
uint16 protocol_length;
|
uint16 protocol_length;
|
||||||
@ -57,15 +57,15 @@ class SctpUtilsTest : public testing::Test {
|
|||||||
channel_type);
|
channel_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_TRUE(buffer.ReadUInt16(&reliability));
|
ASSERT_TRUE(buffer.ReadUInt16(&priority));
|
||||||
|
|
||||||
|
ASSERT_TRUE(buffer.ReadUInt32(&reliability));
|
||||||
if (config.maxRetransmits > -1 || config.maxRetransmitTime > -1) {
|
if (config.maxRetransmits > -1 || config.maxRetransmitTime > -1) {
|
||||||
EXPECT_EQ(config.maxRetransmits > -1 ?
|
EXPECT_EQ(config.maxRetransmits > -1 ?
|
||||||
config.maxRetransmits : config.maxRetransmitTime,
|
config.maxRetransmits : config.maxRetransmitTime,
|
||||||
reliability);
|
static_cast<int>(reliability));
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_TRUE(buffer.ReadUInt16(&priority));
|
|
||||||
|
|
||||||
ASSERT_TRUE(buffer.ReadUInt16(&label_length));
|
ASSERT_TRUE(buffer.ReadUInt16(&label_length));
|
||||||
ASSERT_TRUE(buffer.ReadUInt16(&protocol_length));
|
ASSERT_TRUE(buffer.ReadUInt16(&protocol_length));
|
||||||
EXPECT_EQ(label.size(), label_length);
|
EXPECT_EQ(label.size(), label_length);
|
||||||
@ -86,13 +86,14 @@ TEST_F(SctpUtilsTest, WriteParseMessageWithOrderedReliable) {
|
|||||||
config.protocol = "y";
|
config.protocol = "y";
|
||||||
|
|
||||||
talk_base::Buffer packet;
|
talk_base::Buffer packet;
|
||||||
ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
ASSERT_TRUE(
|
||||||
|
cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||||
|
|
||||||
VerifyOpenMessageFormat(packet, input_label, config);
|
VerifyOpenMessageFormat(packet, input_label, config);
|
||||||
|
|
||||||
std::string output_label;
|
std::string output_label;
|
||||||
webrtc::DataChannelInit output_config;
|
webrtc::DataChannelInit output_config;
|
||||||
ASSERT(cricket::ParseDataChannelOpenMessage(
|
ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
|
||||||
packet, &output_label, &output_config));
|
packet, &output_label, &output_config));
|
||||||
|
|
||||||
EXPECT_EQ(input_label, output_label);
|
EXPECT_EQ(input_label, output_label);
|
||||||
@ -110,19 +111,21 @@ TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmitTime) {
|
|||||||
config.protocol = "y";
|
config.protocol = "y";
|
||||||
|
|
||||||
talk_base::Buffer packet;
|
talk_base::Buffer packet;
|
||||||
ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
ASSERT_TRUE(
|
||||||
|
cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||||
|
|
||||||
VerifyOpenMessageFormat(packet, input_label, config);
|
VerifyOpenMessageFormat(packet, input_label, config);
|
||||||
|
|
||||||
std::string output_label;
|
std::string output_label;
|
||||||
webrtc::DataChannelInit output_config;
|
webrtc::DataChannelInit output_config;
|
||||||
ASSERT(cricket::ParseDataChannelOpenMessage(
|
ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
|
||||||
packet, &output_label, &output_config));
|
packet, &output_label, &output_config));
|
||||||
|
|
||||||
EXPECT_EQ(input_label, output_label);
|
EXPECT_EQ(input_label, output_label);
|
||||||
EXPECT_EQ(config.protocol, output_config.protocol);
|
EXPECT_EQ(config.protocol, output_config.protocol);
|
||||||
EXPECT_EQ(config.ordered, output_config.ordered);
|
EXPECT_EQ(config.ordered, output_config.ordered);
|
||||||
EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime);
|
EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime);
|
||||||
|
EXPECT_EQ(-1, output_config.maxRetransmits);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) {
|
TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) {
|
||||||
@ -132,17 +135,19 @@ TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) {
|
|||||||
config.protocol = "y";
|
config.protocol = "y";
|
||||||
|
|
||||||
talk_base::Buffer packet;
|
talk_base::Buffer packet;
|
||||||
ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
ASSERT_TRUE(
|
||||||
|
cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||||
|
|
||||||
VerifyOpenMessageFormat(packet, input_label, config);
|
VerifyOpenMessageFormat(packet, input_label, config);
|
||||||
|
|
||||||
std::string output_label;
|
std::string output_label;
|
||||||
webrtc::DataChannelInit output_config;
|
webrtc::DataChannelInit output_config;
|
||||||
ASSERT(cricket::ParseDataChannelOpenMessage(
|
ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
|
||||||
packet, &output_label, &output_config));
|
packet, &output_label, &output_config));
|
||||||
|
|
||||||
EXPECT_EQ(input_label, output_label);
|
EXPECT_EQ(input_label, output_label);
|
||||||
EXPECT_EQ(config.protocol, output_config.protocol);
|
EXPECT_EQ(config.protocol, output_config.protocol);
|
||||||
EXPECT_EQ(config.ordered, output_config.ordered);
|
EXPECT_EQ(config.ordered, output_config.ordered);
|
||||||
EXPECT_EQ(config.maxRetransmits, output_config.maxRetransmits);
|
EXPECT_EQ(config.maxRetransmits, output_config.maxRetransmits);
|
||||||
|
EXPECT_EQ(-1, output_config.maxRetransmitTime);
|
||||||
}
|
}
|
||||||
|
@ -1046,7 +1046,14 @@ class FakeWebRtcVideoEngine
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
WEBRTC_STUB(EnableColorEnhancement, (const int, const bool));
|
WEBRTC_STUB(EnableColorEnhancement, (const int, const bool));
|
||||||
|
#ifdef USE_WEBRTC_DEV_BRANCH
|
||||||
|
WEBRTC_VOID_STUB(RegisterPreEncodeCallback,
|
||||||
|
(int, webrtc::I420FrameCallback*));
|
||||||
|
WEBRTC_VOID_STUB(DeRegisterPreEncodeCallback, (int));
|
||||||
|
WEBRTC_VOID_STUB(RegisterPreRenderCallback,
|
||||||
|
(int, webrtc::I420FrameCallback*));
|
||||||
|
WEBRTC_VOID_STUB(DeRegisterPreRenderCallback, (int));
|
||||||
|
#endif
|
||||||
// webrtc::ViEExternalCodec
|
// webrtc::ViEExternalCodec
|
||||||
WEBRTC_FUNC(RegisterExternalSendCodec,
|
WEBRTC_FUNC(RegisterExternalSendCodec,
|
||||||
(const int channel, const unsigned char pl_type, webrtc::VideoEncoder*,
|
(const int channel, const unsigned char pl_type, webrtc::VideoEncoder*,
|
||||||
|
@ -87,6 +87,8 @@ class FakeWebRtcVoiceEngine
|
|||||||
fec(false),
|
fec(false),
|
||||||
nack(false),
|
nack(false),
|
||||||
media_processor_registered(false),
|
media_processor_registered(false),
|
||||||
|
rx_agc_enabled(false),
|
||||||
|
rx_agc_mode(webrtc::kAgcDefault),
|
||||||
cn8_type(13),
|
cn8_type(13),
|
||||||
cn16_type(105),
|
cn16_type(105),
|
||||||
dtmf_type(106),
|
dtmf_type(106),
|
||||||
@ -95,6 +97,7 @@ class FakeWebRtcVoiceEngine
|
|||||||
send_ssrc(0),
|
send_ssrc(0),
|
||||||
level_header_ext_(-1) {
|
level_header_ext_(-1) {
|
||||||
memset(&send_codec, 0, sizeof(send_codec));
|
memset(&send_codec, 0, sizeof(send_codec));
|
||||||
|
memset(&rx_agc_config, 0, sizeof(rx_agc_config));
|
||||||
}
|
}
|
||||||
bool external_transport;
|
bool external_transport;
|
||||||
bool send;
|
bool send;
|
||||||
@ -107,6 +110,9 @@ class FakeWebRtcVoiceEngine
|
|||||||
bool fec;
|
bool fec;
|
||||||
bool nack;
|
bool nack;
|
||||||
bool media_processor_registered;
|
bool media_processor_registered;
|
||||||
|
bool rx_agc_enabled;
|
||||||
|
webrtc::AgcModes rx_agc_mode;
|
||||||
|
webrtc::AgcConfig rx_agc_config;
|
||||||
int cn8_type;
|
int cn8_type;
|
||||||
int cn16_type;
|
int cn16_type;
|
||||||
int dtmf_type;
|
int dtmf_type;
|
||||||
@ -144,6 +150,8 @@ class FakeWebRtcVoiceEngine
|
|||||||
send_fail_channel_(-1),
|
send_fail_channel_(-1),
|
||||||
fail_start_recording_microphone_(false),
|
fail_start_recording_microphone_(false),
|
||||||
recording_microphone_(false),
|
recording_microphone_(false),
|
||||||
|
recording_sample_rate_(-1),
|
||||||
|
playout_sample_rate_(-1),
|
||||||
media_processor_(NULL) {
|
media_processor_(NULL) {
|
||||||
memset(&agc_config_, 0, sizeof(agc_config_));
|
memset(&agc_config_, 0, sizeof(agc_config_));
|
||||||
}
|
}
|
||||||
@ -584,10 +592,22 @@ class FakeWebRtcVoiceEngine
|
|||||||
WEBRTC_STUB(AudioDeviceControl, (unsigned int, unsigned int, unsigned int));
|
WEBRTC_STUB(AudioDeviceControl, (unsigned int, unsigned int, unsigned int));
|
||||||
WEBRTC_STUB(SetLoudspeakerStatus, (bool enable));
|
WEBRTC_STUB(SetLoudspeakerStatus, (bool enable));
|
||||||
WEBRTC_STUB(GetLoudspeakerStatus, (bool& enabled));
|
WEBRTC_STUB(GetLoudspeakerStatus, (bool& enabled));
|
||||||
WEBRTC_STUB(SetRecordingSampleRate, (unsigned int samples_per_sec));
|
WEBRTC_FUNC(SetRecordingSampleRate, (unsigned int samples_per_sec)) {
|
||||||
WEBRTC_STUB_CONST(RecordingSampleRate, (unsigned int* samples_per_sec));
|
recording_sample_rate_ = samples_per_sec;
|
||||||
WEBRTC_STUB(SetPlayoutSampleRate, (unsigned int samples_per_sec));
|
return 0;
|
||||||
WEBRTC_STUB_CONST(PlayoutSampleRate, (unsigned int* samples_per_sec));
|
}
|
||||||
|
WEBRTC_FUNC_CONST(RecordingSampleRate, (unsigned int* samples_per_sec)) {
|
||||||
|
*samples_per_sec = recording_sample_rate_;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
WEBRTC_FUNC(SetPlayoutSampleRate, (unsigned int samples_per_sec)) {
|
||||||
|
playout_sample_rate_ = samples_per_sec;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
WEBRTC_FUNC_CONST(PlayoutSampleRate, (unsigned int* samples_per_sec)) {
|
||||||
|
*samples_per_sec = playout_sample_rate_;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
WEBRTC_STUB(EnableBuiltInAEC, (bool enable));
|
WEBRTC_STUB(EnableBuiltInAEC, (bool enable));
|
||||||
virtual bool BuiltInAECIsEnabled() const { return true; }
|
virtual bool BuiltInAECIsEnabled() const { return true; }
|
||||||
|
|
||||||
@ -841,12 +861,27 @@ class FakeWebRtcVoiceEngine
|
|||||||
WEBRTC_STUB(SetRxNsStatus, (int channel, bool enable, webrtc::NsModes mode));
|
WEBRTC_STUB(SetRxNsStatus, (int channel, bool enable, webrtc::NsModes mode));
|
||||||
WEBRTC_STUB(GetRxNsStatus, (int channel, bool& enabled,
|
WEBRTC_STUB(GetRxNsStatus, (int channel, bool& enabled,
|
||||||
webrtc::NsModes& mode));
|
webrtc::NsModes& mode));
|
||||||
WEBRTC_STUB(SetRxAgcStatus, (int channel, bool enable,
|
WEBRTC_FUNC(SetRxAgcStatus, (int channel, bool enable,
|
||||||
webrtc::AgcModes mode));
|
webrtc::AgcModes mode)) {
|
||||||
WEBRTC_STUB(GetRxAgcStatus, (int channel, bool& enabled,
|
channels_[channel]->rx_agc_enabled = enable;
|
||||||
webrtc::AgcModes& mode));
|
channels_[channel]->rx_agc_mode = mode;
|
||||||
WEBRTC_STUB(SetRxAgcConfig, (int channel, webrtc::AgcConfig config));
|
return 0;
|
||||||
WEBRTC_STUB(GetRxAgcConfig, (int channel, webrtc::AgcConfig& config));
|
}
|
||||||
|
WEBRTC_FUNC(GetRxAgcStatus, (int channel, bool& enabled,
|
||||||
|
webrtc::AgcModes& mode)) {
|
||||||
|
enabled = channels_[channel]->rx_agc_enabled;
|
||||||
|
mode = channels_[channel]->rx_agc_mode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBRTC_FUNC(SetRxAgcConfig, (int channel, webrtc::AgcConfig config)) {
|
||||||
|
channels_[channel]->rx_agc_config = config;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
WEBRTC_FUNC(GetRxAgcConfig, (int channel, webrtc::AgcConfig& config)) {
|
||||||
|
config = channels_[channel]->rx_agc_config;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
WEBRTC_STUB(RegisterRxVadObserver, (int, webrtc::VoERxVadCallback&));
|
WEBRTC_STUB(RegisterRxVadObserver, (int, webrtc::VoERxVadCallback&));
|
||||||
WEBRTC_STUB(DeRegisterRxVadObserver, (int channel));
|
WEBRTC_STUB(DeRegisterRxVadObserver, (int channel));
|
||||||
@ -996,6 +1031,8 @@ class FakeWebRtcVoiceEngine
|
|||||||
int send_fail_channel_;
|
int send_fail_channel_;
|
||||||
bool fail_start_recording_microphone_;
|
bool fail_start_recording_microphone_;
|
||||||
bool recording_microphone_;
|
bool recording_microphone_;
|
||||||
|
int recording_sample_rate_;
|
||||||
|
int playout_sample_rate_;
|
||||||
DtmfInfo dtmf_info_;
|
DtmfInfo dtmf_info_;
|
||||||
webrtc::VoEMediaProcess* media_processor_;
|
webrtc::VoEMediaProcess* media_processor_;
|
||||||
};
|
};
|
||||||
|
@ -309,6 +309,13 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
|
|||||||
: video_channel_(video_channel),
|
: video_channel_(video_channel),
|
||||||
framerate_(0),
|
framerate_(0),
|
||||||
bitrate_(0),
|
bitrate_(0),
|
||||||
|
decode_ms_(0),
|
||||||
|
max_decode_ms_(0),
|
||||||
|
current_delay_ms_(0),
|
||||||
|
target_delay_ms_(0),
|
||||||
|
jitter_buffer_ms_(0),
|
||||||
|
min_playout_delay_ms_(0),
|
||||||
|
render_delay_ms_(0),
|
||||||
firs_requested_(0) {
|
firs_requested_(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,23 +330,42 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
|
|||||||
framerate_ = framerate;
|
framerate_ = framerate;
|
||||||
bitrate_ = bitrate;
|
bitrate_ = bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void DecoderTiming(int decode_ms,
|
||||||
|
int max_decode_ms,
|
||||||
|
int current_delay_ms,
|
||||||
|
int target_delay_ms,
|
||||||
|
int jitter_buffer_ms,
|
||||||
|
int min_playout_delay_ms,
|
||||||
|
int render_delay_ms) {
|
||||||
|
talk_base::CritScope cs(&crit_);
|
||||||
|
decode_ms_ = decode_ms;
|
||||||
|
max_decode_ms_ = max_decode_ms;
|
||||||
|
current_delay_ms_ = current_delay_ms;
|
||||||
|
target_delay_ms_ = target_delay_ms;
|
||||||
|
jitter_buffer_ms_ = jitter_buffer_ms;
|
||||||
|
min_playout_delay_ms_ = min_playout_delay_ms;
|
||||||
|
render_delay_ms_ = render_delay_ms;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void RequestNewKeyFrame(const int videoChannel) {
|
virtual void RequestNewKeyFrame(const int videoChannel) {
|
||||||
talk_base::CritScope cs(&crit_);
|
talk_base::CritScope cs(&crit_);
|
||||||
ASSERT(video_channel_ == videoChannel);
|
ASSERT(video_channel_ == videoChannel);
|
||||||
++firs_requested_;
|
++firs_requested_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int framerate() const {
|
// Populate |rinfo| based on previously-set data in |*this|.
|
||||||
|
void ExportTo(VideoReceiverInfo* rinfo) {
|
||||||
talk_base::CritScope cs(&crit_);
|
talk_base::CritScope cs(&crit_);
|
||||||
return framerate_;
|
rinfo->firs_sent = firs_requested_;
|
||||||
}
|
rinfo->framerate_rcvd = framerate_;
|
||||||
int bitrate() const {
|
rinfo->decode_ms = decode_ms_;
|
||||||
talk_base::CritScope cs(&crit_);
|
rinfo->max_decode_ms = max_decode_ms_;
|
||||||
return bitrate_;
|
rinfo->current_delay_ms = current_delay_ms_;
|
||||||
}
|
rinfo->target_delay_ms = target_delay_ms_;
|
||||||
int firs_requested() const {
|
rinfo->jitter_buffer_ms = jitter_buffer_ms_;
|
||||||
talk_base::CritScope cs(&crit_);
|
rinfo->min_playout_delay_ms = min_playout_delay_ms_;
|
||||||
return firs_requested_;
|
rinfo->render_delay_ms = render_delay_ms_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -347,6 +373,13 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
|
|||||||
int video_channel_;
|
int video_channel_;
|
||||||
int framerate_;
|
int framerate_;
|
||||||
int bitrate_;
|
int bitrate_;
|
||||||
|
int decode_ms_;
|
||||||
|
int max_decode_ms_;
|
||||||
|
int current_delay_ms_;
|
||||||
|
int target_delay_ms_;
|
||||||
|
int jitter_buffer_ms_;
|
||||||
|
int min_playout_delay_ms_;
|
||||||
|
int render_delay_ms_;
|
||||||
int firs_requested_;
|
int firs_requested_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2303,14 +2336,13 @@ bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) {
|
|||||||
rinfo.packets_lost = -1;
|
rinfo.packets_lost = -1;
|
||||||
rinfo.packets_concealed = -1;
|
rinfo.packets_concealed = -1;
|
||||||
rinfo.fraction_lost = -1; // from SentRTCP
|
rinfo.fraction_lost = -1; // from SentRTCP
|
||||||
rinfo.firs_sent = channel->decoder_observer()->firs_requested();
|
|
||||||
rinfo.nacks_sent = -1;
|
rinfo.nacks_sent = -1;
|
||||||
rinfo.frame_width = channel->render_adapter()->width();
|
rinfo.frame_width = channel->render_adapter()->width();
|
||||||
rinfo.frame_height = channel->render_adapter()->height();
|
rinfo.frame_height = channel->render_adapter()->height();
|
||||||
rinfo.framerate_rcvd = channel->decoder_observer()->framerate();
|
|
||||||
int fps = channel->render_adapter()->framerate();
|
int fps = channel->render_adapter()->framerate();
|
||||||
rinfo.framerate_decoded = fps;
|
rinfo.framerate_decoded = fps;
|
||||||
rinfo.framerate_output = fps;
|
rinfo.framerate_output = fps;
|
||||||
|
channel->decoder_observer()->ExportTo(&rinfo);
|
||||||
|
|
||||||
// Get sent RTCP statistics.
|
// Get sent RTCP statistics.
|
||||||
uint16 s_fraction_lost;
|
uint16 s_fraction_lost;
|
||||||
|
@ -118,7 +118,7 @@ class WebRtcVideoEngineTestFake : public testing::Test,
|
|||||||
}
|
}
|
||||||
cricket::WebRtcVideoFrame frame;
|
cricket::WebRtcVideoFrame frame;
|
||||||
size_t size = width * height * 3 / 2; // I420
|
size_t size = width * height * 3 / 2; // I420
|
||||||
talk_base::scoped_array<uint8> pixel(new uint8[size]);
|
talk_base::scoped_ptr<uint8[]> pixel(new uint8[size]);
|
||||||
if (!frame.Init(cricket::FOURCC_I420,
|
if (!frame.Init(cricket::FOURCC_I420,
|
||||||
width, height, width, height,
|
width, height, width, height,
|
||||||
pixel.get(), size, 1, 1, 0, 0, 0)) {
|
pixel.get(), size, 1, 1, 0, 0, 0)) {
|
||||||
@ -138,7 +138,7 @@ class WebRtcVideoEngineTestFake : public testing::Test,
|
|||||||
}
|
}
|
||||||
cricket::WebRtcVideoFrame frame;
|
cricket::WebRtcVideoFrame frame;
|
||||||
size_t size = width * height * 3 / 2; // I420
|
size_t size = width * height * 3 / 2; // I420
|
||||||
talk_base::scoped_array<uint8> pixel(new uint8[size]);
|
talk_base::scoped_ptr<uint8[]> pixel(new uint8[size]);
|
||||||
if (!frame.Init(cricket::FOURCC_I420,
|
if (!frame.Init(cricket::FOURCC_I420,
|
||||||
width, height, width, height,
|
width, height, width, height,
|
||||||
pixel.get(), size, 1, 1, 0, timestamp, 0)) {
|
pixel.get(), size, 1, 1, 0, timestamp, 0)) {
|
||||||
@ -1161,7 +1161,8 @@ TEST_F(WebRtcVideoEngineTestFake, SetOptionsWithDenoising) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(WebRtcVideoEngineTestFake, SendReceiveBitratesStats) {
|
// Disabled since its flaky: b/11288120
|
||||||
|
TEST_F(WebRtcVideoEngineTestFake, DISABLED_SendReceiveBitratesStats) {
|
||||||
EXPECT_TRUE(SetupEngine());
|
EXPECT_TRUE(SetupEngine());
|
||||||
cricket::VideoOptions options;
|
cricket::VideoOptions options;
|
||||||
options.conference_mode.Set(true);
|
options.conference_mode.Set(true);
|
||||||
|
@ -55,7 +55,7 @@ class FrameBuffer {
|
|||||||
const webrtc::VideoFrame* frame() const;
|
const webrtc::VideoFrame* frame() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
talk_base::scoped_array<char> data_;
|
talk_base::scoped_ptr<char[]> data_;
|
||||||
size_t length_;
|
size_t length_;
|
||||||
webrtc::VideoFrame video_frame_;
|
webrtc::VideoFrame video_frame_;
|
||||||
};
|
};
|
||||||
|
@ -53,7 +53,7 @@ class WebRtcVideoFrameTest : public VideoFrameTest<cricket::WebRtcVideoFrame> {
|
|||||||
captured_frame.height = frame_height;
|
captured_frame.height = frame_height;
|
||||||
captured_frame.data_size = (frame_width * frame_height) +
|
captured_frame.data_size = (frame_width * frame_height) +
|
||||||
((frame_width + 1) / 2) * ((frame_height + 1) / 2) * 2;
|
((frame_width + 1) / 2) * ((frame_height + 1) / 2) * 2;
|
||||||
talk_base::scoped_array<uint8> captured_frame_buffer(
|
talk_base::scoped_ptr<uint8[]> captured_frame_buffer(
|
||||||
new uint8[captured_frame.data_size]);
|
new uint8[captured_frame.data_size]);
|
||||||
captured_frame.data = captured_frame_buffer.get();
|
captured_frame.data = captured_frame_buffer.get();
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "webrtc/video_engine/include/vie_network.h"
|
#include "webrtc/video_engine/include/vie_network.h"
|
||||||
#include "webrtc/video_engine/include/vie_render.h"
|
#include "webrtc/video_engine/include/vie_render.h"
|
||||||
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
|
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
|
||||||
|
#include "webrtc/video_engine/new_include/frame_callback.h"
|
||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
|
@ -528,7 +528,7 @@ bool WebRtcVoiceEngine::InitInternal() {
|
|||||||
// Save the default AGC configuration settings. This must happen before
|
// Save the default AGC configuration settings. This must happen before
|
||||||
// calling SetOptions or the default will be overwritten.
|
// calling SetOptions or the default will be overwritten.
|
||||||
if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) {
|
if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) {
|
||||||
LOG_RTCERR0(GetAGCConfig);
|
LOG_RTCERR0(GetAgcConfig);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,6 +686,10 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
|||||||
webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
|
webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
|
||||||
webrtc::NsModes ns_mode = webrtc::kNsHighSuppression;
|
webrtc::NsModes ns_mode = webrtc::kNsHighSuppression;
|
||||||
bool aecm_comfort_noise = false;
|
bool aecm_comfort_noise = false;
|
||||||
|
if (options.aecm_generate_comfort_noise.Get(&aecm_comfort_noise)) {
|
||||||
|
LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
|
||||||
|
<< aecm_comfort_noise << " (default is false).";
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(IOS)
|
#if defined(IOS)
|
||||||
// On iOS, VPIO provides built-in EC and AGC.
|
// On iOS, VPIO provides built-in EC and AGC.
|
||||||
@ -713,6 +717,9 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
|||||||
if (voep->SetEcStatus(echo_cancellation, ec_mode) == -1) {
|
if (voep->SetEcStatus(echo_cancellation, ec_mode) == -1) {
|
||||||
LOG_RTCERR2(SetEcStatus, echo_cancellation, ec_mode);
|
LOG_RTCERR2(SetEcStatus, echo_cancellation, ec_mode);
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
LOG(LS_VERBOSE) << "Echo control set to " << echo_cancellation
|
||||||
|
<< " with mode " << ec_mode;
|
||||||
}
|
}
|
||||||
#if !defined(ANDROID)
|
#if !defined(ANDROID)
|
||||||
// TODO(ajm): Remove the error return on Android from webrtc.
|
// TODO(ajm): Remove the error return on Android from webrtc.
|
||||||
@ -734,6 +741,38 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
|||||||
if (voep->SetAgcStatus(auto_gain_control, agc_mode) == -1) {
|
if (voep->SetAgcStatus(auto_gain_control, agc_mode) == -1) {
|
||||||
LOG_RTCERR2(SetAgcStatus, auto_gain_control, agc_mode);
|
LOG_RTCERR2(SetAgcStatus, auto_gain_control, agc_mode);
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
LOG(LS_VERBOSE) << "Auto gain set to " << auto_gain_control
|
||||||
|
<< " with mode " << agc_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.tx_agc_target_dbov.IsSet() ||
|
||||||
|
options.tx_agc_digital_compression_gain.IsSet() ||
|
||||||
|
options.tx_agc_limiter.IsSet()) {
|
||||||
|
// Override default_agc_config_. Generally, an unset option means "leave
|
||||||
|
// the VoE bits alone" in this function, so we want whatever is set to be
|
||||||
|
// stored as the new "default". If we didn't, then setting e.g.
|
||||||
|
// tx_agc_target_dbov would reset digital compression gain and limiter
|
||||||
|
// settings.
|
||||||
|
// Also, if we don't update default_agc_config_, then adjust_agc_delta
|
||||||
|
// would be an offset from the original values, and not whatever was set
|
||||||
|
// explicitly.
|
||||||
|
default_agc_config_.targetLeveldBOv =
|
||||||
|
options.tx_agc_target_dbov.GetWithDefaultIfUnset(
|
||||||
|
default_agc_config_.targetLeveldBOv);
|
||||||
|
default_agc_config_.digitalCompressionGaindB =
|
||||||
|
options.tx_agc_digital_compression_gain.GetWithDefaultIfUnset(
|
||||||
|
default_agc_config_.digitalCompressionGaindB);
|
||||||
|
default_agc_config_.limiterEnable =
|
||||||
|
options.tx_agc_limiter.GetWithDefaultIfUnset(
|
||||||
|
default_agc_config_.limiterEnable);
|
||||||
|
if (voe_wrapper_->processing()->SetAgcConfig(default_agc_config_) == -1) {
|
||||||
|
LOG_RTCERR3(SetAgcConfig,
|
||||||
|
default_agc_config_.targetLeveldBOv,
|
||||||
|
default_agc_config_.digitalCompressionGaindB,
|
||||||
|
default_agc_config_.limiterEnable);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,6 +781,9 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
|||||||
if (voep->SetNsStatus(noise_suppression, ns_mode) == -1) {
|
if (voep->SetNsStatus(noise_suppression, ns_mode) == -1) {
|
||||||
LOG_RTCERR2(SetNsStatus, noise_suppression, ns_mode);
|
LOG_RTCERR2(SetNsStatus, noise_suppression, ns_mode);
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
LOG(LS_VERBOSE) << "Noise suppression set to " << noise_suppression
|
||||||
|
<< " with mode " << ns_mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,6 +841,20 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 recording_sample_rate;
|
||||||
|
if (options.recording_sample_rate.Get(&recording_sample_rate)) {
|
||||||
|
if (voe_wrapper_->hw()->SetRecordingSampleRate(recording_sample_rate)) {
|
||||||
|
LOG_RTCERR1(SetRecordingSampleRate, recording_sample_rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 playout_sample_rate;
|
||||||
|
if (options.playout_sample_rate.Get(&playout_sample_rate)) {
|
||||||
|
if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) {
|
||||||
|
LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1136,6 +1192,18 @@ void WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow trace options to override the trace filter. We default
|
||||||
|
// it to log_filter_ (as a translation of libjingle log levels)
|
||||||
|
// elsewhere, but this allows clients to explicitly set webrtc
|
||||||
|
// log levels.
|
||||||
|
std::vector<std::string>::iterator tracefilter =
|
||||||
|
std::find(opts.begin(), opts.end(), "tracefilter");
|
||||||
|
if (tracefilter != opts.end() && ++tracefilter != opts.end()) {
|
||||||
|
if (!tracing_->SetTraceFilter(talk_base::FromString<int>(*tracefilter))) {
|
||||||
|
LOG_RTCERR1(SetTraceFilter, *tracefilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set AEC dump file
|
// Set AEC dump file
|
||||||
std::vector<std::string>::iterator recordEC =
|
std::vector<std::string>::iterator recordEC =
|
||||||
std::find(opts.begin(), opts.end(), "recordEC");
|
std::find(opts.begin(), opts.end(), "recordEC");
|
||||||
@ -1587,6 +1655,56 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
|
|||||||
// Will be interpreted when appropriate.
|
// Will be interpreted when appropriate.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Receiver-side auto gain control happens per channel, so set it here from
|
||||||
|
// options. Note that, like conference mode, setting it on the engine won't
|
||||||
|
// have the desired effect, since voice channels don't inherit options from
|
||||||
|
// the media engine when those options are applied per-channel.
|
||||||
|
bool rx_auto_gain_control;
|
||||||
|
if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) {
|
||||||
|
if (engine()->voe()->processing()->SetRxAgcStatus(
|
||||||
|
voe_channel(), rx_auto_gain_control,
|
||||||
|
webrtc::kAgcFixedDigital) == -1) {
|
||||||
|
LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control
|
||||||
|
<< " with mode " << webrtc::kAgcFixedDigital;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (options.rx_agc_target_dbov.IsSet() ||
|
||||||
|
options.rx_agc_digital_compression_gain.IsSet() ||
|
||||||
|
options.rx_agc_limiter.IsSet()) {
|
||||||
|
webrtc::AgcConfig config;
|
||||||
|
// If only some of the options are being overridden, get the current
|
||||||
|
// settings for the channel and bail if they aren't available.
|
||||||
|
if (!options.rx_agc_target_dbov.IsSet() ||
|
||||||
|
!options.rx_agc_digital_compression_gain.IsSet() ||
|
||||||
|
!options.rx_agc_limiter.IsSet()) {
|
||||||
|
if (engine()->voe()->processing()->GetRxAgcConfig(
|
||||||
|
voe_channel(), config) != 0) {
|
||||||
|
LOG(LS_ERROR) << "Failed to get default rx agc configuration for "
|
||||||
|
<< "channel " << voe_channel() << ". Since not all rx "
|
||||||
|
<< "agc options are specified, unable to safely set rx "
|
||||||
|
<< "agc options.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.targetLeveldBOv =
|
||||||
|
options.rx_agc_target_dbov.GetWithDefaultIfUnset(
|
||||||
|
config.targetLeveldBOv);
|
||||||
|
config.digitalCompressionGaindB =
|
||||||
|
options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset(
|
||||||
|
config.digitalCompressionGaindB);
|
||||||
|
config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset(
|
||||||
|
config.limiterEnable);
|
||||||
|
if (engine()->voe()->processing()->SetRxAgcConfig(
|
||||||
|
voe_channel(), config) == -1) {
|
||||||
|
LOG_RTCERR4(SetRxAgcConfig, voe_channel(), config.targetLeveldBOv,
|
||||||
|
config.digitalCompressionGaindB, config.limiterEnable);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG(LS_INFO) << "Set voice channel options. Current options: "
|
LOG(LS_INFO) << "Set voice channel options. Current options: "
|
||||||
<< options_.ToString();
|
<< options_.ToString();
|
||||||
return true;
|
return true;
|
||||||
|
@ -55,9 +55,10 @@ class FakeVoEWrapper : public cricket::VoEWrapper {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NullVoETraceWrapper : public cricket::VoETraceWrapper {
|
class FakeVoETraceWrapper : public cricket::VoETraceWrapper {
|
||||||
public:
|
public:
|
||||||
virtual int SetTraceFilter(const unsigned int filter) {
|
virtual int SetTraceFilter(const unsigned int filter) {
|
||||||
|
filter_ = filter;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
virtual int SetTraceFile(const char* fileNameUTF8) {
|
virtual int SetTraceFile(const char* fileNameUTF8) {
|
||||||
@ -66,6 +67,7 @@ class NullVoETraceWrapper : public cricket::VoETraceWrapper {
|
|||||||
virtual int SetTraceCallback(webrtc::TraceCallback* callback) {
|
virtual int SetTraceCallback(webrtc::TraceCallback* callback) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
unsigned int filter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebRtcVoiceEngineTestFake : public testing::Test {
|
class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||||
@ -102,9 +104,10 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
|||||||
WebRtcVoiceEngineTestFake()
|
WebRtcVoiceEngineTestFake()
|
||||||
: voe_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
|
: voe_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
|
||||||
voe_sc_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
|
voe_sc_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
|
||||||
|
trace_wrapper_(new FakeVoETraceWrapper()),
|
||||||
engine_(new FakeVoEWrapper(&voe_),
|
engine_(new FakeVoEWrapper(&voe_),
|
||||||
new FakeVoEWrapper(&voe_sc_),
|
new FakeVoEWrapper(&voe_sc_),
|
||||||
new NullVoETraceWrapper()),
|
trace_wrapper_),
|
||||||
channel_(NULL), soundclip_(NULL) {
|
channel_(NULL), soundclip_(NULL) {
|
||||||
options_conference_.conference_mode.Set(true);
|
options_conference_.conference_mode.Set(true);
|
||||||
options_adjust_agc_.adjust_agc_delta.Set(-10);
|
options_adjust_agc_.adjust_agc_delta.Set(-10);
|
||||||
@ -277,6 +280,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
|||||||
protected:
|
protected:
|
||||||
cricket::FakeWebRtcVoiceEngine voe_;
|
cricket::FakeWebRtcVoiceEngine voe_;
|
||||||
cricket::FakeWebRtcVoiceEngine voe_sc_;
|
cricket::FakeWebRtcVoiceEngine voe_sc_;
|
||||||
|
FakeVoETraceWrapper* trace_wrapper_;
|
||||||
cricket::WebRtcVoiceEngine engine_;
|
cricket::WebRtcVoiceEngine engine_;
|
||||||
cricket::VoiceMediaChannel* channel_;
|
cricket::VoiceMediaChannel* channel_;
|
||||||
cricket::SoundclipMedia* soundclip_;
|
cricket::SoundclipMedia* soundclip_;
|
||||||
@ -1873,6 +1877,84 @@ TEST_F(WebRtcVoiceEngineTestFake, CodianSendAndPlayout) {
|
|||||||
EXPECT_FALSE(voe_.GetPlayout(channel_num));
|
EXPECT_FALSE(voe_.GetPlayout(channel_num));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WebRtcVoiceEngineTestFake, TxAgcConfigViaOptions) {
|
||||||
|
EXPECT_TRUE(SetupEngine());
|
||||||
|
webrtc::AgcConfig agc_config;
|
||||||
|
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||||
|
EXPECT_EQ(0, agc_config.targetLeveldBOv);
|
||||||
|
|
||||||
|
cricket::AudioOptions options;
|
||||||
|
options.tx_agc_target_dbov.Set(3);
|
||||||
|
options.tx_agc_digital_compression_gain.Set(9);
|
||||||
|
options.tx_agc_limiter.Set(true);
|
||||||
|
options.auto_gain_control.Set(true);
|
||||||
|
EXPECT_TRUE(engine_.SetOptions(options));
|
||||||
|
|
||||||
|
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||||
|
EXPECT_EQ(3, agc_config.targetLeveldBOv);
|
||||||
|
EXPECT_EQ(9, agc_config.digitalCompressionGaindB);
|
||||||
|
EXPECT_TRUE(agc_config.limiterEnable);
|
||||||
|
|
||||||
|
// Check interaction with adjust_agc_delta. Both should be respected, for
|
||||||
|
// backwards compatibility.
|
||||||
|
options.adjust_agc_delta.Set(-10);
|
||||||
|
EXPECT_TRUE(engine_.SetOptions(options));
|
||||||
|
|
||||||
|
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
|
||||||
|
EXPECT_EQ(13, agc_config.targetLeveldBOv);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WebRtcVoiceEngineTestFake, RxAgcConfigViaOptions) {
|
||||||
|
EXPECT_TRUE(SetupEngine());
|
||||||
|
int channel_num = voe_.GetLastChannel();
|
||||||
|
cricket::AudioOptions options;
|
||||||
|
options.rx_agc_target_dbov.Set(6);
|
||||||
|
options.rx_agc_digital_compression_gain.Set(0);
|
||||||
|
options.rx_agc_limiter.Set(true);
|
||||||
|
options.rx_auto_gain_control.Set(true);
|
||||||
|
EXPECT_TRUE(channel_->SetOptions(options));
|
||||||
|
|
||||||
|
webrtc::AgcConfig agc_config;
|
||||||
|
EXPECT_EQ(0, engine_.voe()->processing()->GetRxAgcConfig(
|
||||||
|
channel_num, agc_config));
|
||||||
|
EXPECT_EQ(6, agc_config.targetLeveldBOv);
|
||||||
|
EXPECT_EQ(0, agc_config.digitalCompressionGaindB);
|
||||||
|
EXPECT_TRUE(agc_config.limiterEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WebRtcVoiceEngineTestFake, SampleRatesViaOptions) {
|
||||||
|
EXPECT_TRUE(SetupEngine());
|
||||||
|
cricket::AudioOptions options;
|
||||||
|
options.recording_sample_rate.Set(48000u);
|
||||||
|
options.playout_sample_rate.Set(44100u);
|
||||||
|
EXPECT_TRUE(engine_.SetOptions(options));
|
||||||
|
|
||||||
|
unsigned int recording_sample_rate, playout_sample_rate;
|
||||||
|
EXPECT_EQ(0, voe_.RecordingSampleRate(&recording_sample_rate));
|
||||||
|
EXPECT_EQ(0, voe_.PlayoutSampleRate(&playout_sample_rate));
|
||||||
|
EXPECT_EQ(48000u, recording_sample_rate);
|
||||||
|
EXPECT_EQ(44100u, playout_sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WebRtcVoiceEngineTestFake, TraceFilterViaTraceOptions) {
|
||||||
|
EXPECT_TRUE(SetupEngine());
|
||||||
|
engine_.SetLogging(talk_base::LS_INFO, "");
|
||||||
|
EXPECT_EQ(
|
||||||
|
// Info:
|
||||||
|
webrtc::kTraceStateInfo | webrtc::kTraceInfo |
|
||||||
|
// Warning:
|
||||||
|
webrtc::kTraceTerseInfo | webrtc::kTraceWarning |
|
||||||
|
// Error:
|
||||||
|
webrtc::kTraceError | webrtc::kTraceCritical,
|
||||||
|
static_cast<int>(trace_wrapper_->filter_));
|
||||||
|
// Now set it explicitly
|
||||||
|
std::string filter =
|
||||||
|
"tracefilter " + talk_base::ToString(webrtc::kTraceDefault);
|
||||||
|
engine_.SetLogging(talk_base::LS_VERBOSE, filter.c_str());
|
||||||
|
EXPECT_EQ(static_cast<unsigned int>(webrtc::kTraceDefault),
|
||||||
|
trace_wrapper_->filter_);
|
||||||
|
}
|
||||||
|
|
||||||
// Test that we can set the outgoing SSRC properly.
|
// Test that we can set the outgoing SSRC properly.
|
||||||
// SSRC is set in SetupEngine by calling AddSendStream.
|
// SSRC is set in SetupEngine by calling AddSendStream.
|
||||||
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {
|
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {
|
||||||
|
@ -233,7 +233,7 @@ class DtlsTestClient : public sigslot::has_slots<> {
|
|||||||
|
|
||||||
void SendPackets(size_t channel, size_t size, size_t count, bool srtp) {
|
void SendPackets(size_t channel, size_t size, size_t count, bool srtp) {
|
||||||
ASSERT(channel < channels_.size());
|
ASSERT(channel < channels_.size());
|
||||||
talk_base::scoped_array<char> packet(new char[size]);
|
talk_base::scoped_ptr<char[]> packet(new char[size]);
|
||||||
size_t sent = 0;
|
size_t sent = 0;
|
||||||
do {
|
do {
|
||||||
// Fill the packet with a known value and a sequence number to check
|
// Fill the packet with a known value and a sequence number to check
|
||||||
|
@ -57,6 +57,11 @@ static const int kOnlyLocalPorts = cricket::PORTALLOCATOR_DISABLE_STUN |
|
|||||||
// Addresses on the public internet.
|
// Addresses on the public internet.
|
||||||
static const SocketAddress kPublicAddrs[2] =
|
static const SocketAddress kPublicAddrs[2] =
|
||||||
{ SocketAddress("11.11.11.11", 0), SocketAddress("22.22.22.22", 0) };
|
{ SocketAddress("11.11.11.11", 0), SocketAddress("22.22.22.22", 0) };
|
||||||
|
// IPv6 Addresses on the public internet.
|
||||||
|
static const SocketAddress kIPv6PublicAddrs[2] = {
|
||||||
|
SocketAddress("2400:4030:1:2c00:be30:abcd:efab:cdef", 0),
|
||||||
|
SocketAddress("2620:0:1000:1b03:2e41:38ff:fea6:f2a4", 0)
|
||||||
|
};
|
||||||
// For configuring multihomed clients.
|
// For configuring multihomed clients.
|
||||||
static const SocketAddress kAlternateAddrs[2] =
|
static const SocketAddress kAlternateAddrs[2] =
|
||||||
{ SocketAddress("11.11.11.101", 0), SocketAddress("22.22.22.202", 0) };
|
{ SocketAddress("11.11.11.101", 0), SocketAddress("22.22.22.202", 0) };
|
||||||
@ -1413,6 +1418,34 @@ TEST_F(P2PTransportChannelTest, TestDefaultDscpValue) {
|
|||||||
GetEndpoint(1)->cd1_.ch_->DefaultDscpValue());
|
GetEndpoint(1)->cd1_.ch_->DefaultDscpValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify IPv6 connection is preferred over IPv4.
|
||||||
|
TEST_F(P2PTransportChannelTest, TestIPv6Connections) {
|
||||||
|
AddAddress(0, kIPv6PublicAddrs[0]);
|
||||||
|
AddAddress(0, kPublicAddrs[0]);
|
||||||
|
AddAddress(1, kIPv6PublicAddrs[1]);
|
||||||
|
AddAddress(1, kPublicAddrs[1]);
|
||||||
|
|
||||||
|
SetAllocationStepDelay(0, kMinimumStepDelay);
|
||||||
|
SetAllocationStepDelay(1, kMinimumStepDelay);
|
||||||
|
|
||||||
|
// Enable IPv6
|
||||||
|
SetAllocatorFlags(0, cricket::PORTALLOCATOR_ENABLE_IPV6);
|
||||||
|
SetAllocatorFlags(1, cricket::PORTALLOCATOR_ENABLE_IPV6);
|
||||||
|
|
||||||
|
CreateChannels(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE_WAIT(ep1_ch1()->readable() && ep1_ch1()->writable() &&
|
||||||
|
ep2_ch1()->readable() && ep2_ch1()->writable(),
|
||||||
|
1000);
|
||||||
|
EXPECT_TRUE(
|
||||||
|
ep1_ch1()->best_connection() && ep2_ch1()->best_connection() &&
|
||||||
|
LocalCandidate(ep1_ch1())->address().EqualIPs(kIPv6PublicAddrs[0]) &&
|
||||||
|
RemoteCandidate(ep1_ch1())->address().EqualIPs(kIPv6PublicAddrs[1]));
|
||||||
|
|
||||||
|
TestSendRecv(1);
|
||||||
|
DestroyChannels();
|
||||||
|
}
|
||||||
|
|
||||||
// Test what happens when we have 2 users behind the same NAT. This can lead
|
// Test what happens when we have 2 users behind the same NAT. This can lead
|
||||||
// to interesting behavior because the STUN server will only give out the
|
// to interesting behavior because the STUN server will only give out the
|
||||||
// address of the outermost NAT.
|
// address of the outermost NAT.
|
||||||
|
@ -215,7 +215,7 @@ class TestChannel : public sigslot::has_slots<> {
|
|||||||
public:
|
public:
|
||||||
TestChannel(Port* p1, Port* p2)
|
TestChannel(Port* p1, Port* p2)
|
||||||
: ice_mode_(ICEMODE_FULL), src_(p1), dst_(p2), complete_count_(0),
|
: ice_mode_(ICEMODE_FULL), src_(p1), dst_(p2), complete_count_(0),
|
||||||
conn_(NULL), remote_request_(NULL), nominated_(false) {
|
conn_(NULL), remote_request_(), nominated_(false) {
|
||||||
src_->SignalPortComplete.connect(
|
src_->SignalPortComplete.connect(
|
||||||
this, &TestChannel::OnPortComplete);
|
this, &TestChannel::OnPortComplete);
|
||||||
src_->SignalUnknownAddress.connect(this, &TestChannel::OnUnknownAddress);
|
src_->SignalUnknownAddress.connect(this, &TestChannel::OnUnknownAddress);
|
||||||
|
@ -539,7 +539,7 @@ IPseudoTcpNotify::WriteResult PseudoTcp::packet(uint32 seq, uint8 flags,
|
|||||||
|
|
||||||
uint32 now = Now();
|
uint32 now = Now();
|
||||||
|
|
||||||
talk_base::scoped_array<uint8> buffer(new uint8[MAX_PACKET]);
|
talk_base::scoped_ptr<uint8[]> buffer(new uint8[MAX_PACKET]);
|
||||||
long_to_bytes(m_conv, buffer.get());
|
long_to_bytes(m_conv, buffer.get());
|
||||||
long_to_bytes(seq, buffer.get() + 4);
|
long_to_bytes(seq, buffer.get() + 4);
|
||||||
long_to_bytes(m_rcv_nxt, buffer.get() + 8);
|
long_to_bytes(m_rcv_nxt, buffer.get() + 8);
|
||||||
|
@ -188,7 +188,7 @@ bool StunMessage::ValidateMessageIntegrity(const char* data, size_t size,
|
|||||||
|
|
||||||
// Getting length of the message to calculate Message Integrity.
|
// Getting length of the message to calculate Message Integrity.
|
||||||
size_t mi_pos = current_pos;
|
size_t mi_pos = current_pos;
|
||||||
talk_base::scoped_array<char> temp_data(new char[current_pos]);
|
talk_base::scoped_ptr<char[]> temp_data(new char[current_pos]);
|
||||||
memcpy(temp_data.get(), data, current_pos);
|
memcpy(temp_data.get(), data, current_pos);
|
||||||
if (size > mi_pos + kStunAttributeHeaderSize + kStunMessageIntegritySize) {
|
if (size > mi_pos + kStunAttributeHeaderSize + kStunMessageIntegritySize) {
|
||||||
// Stun message has other attributes after message integrity.
|
// Stun message has other attributes after message integrity.
|
||||||
|
@ -287,8 +287,13 @@ void UDPPort::SendStunBindingRequest() {
|
|||||||
if (server_addr_.IsUnresolved()) {
|
if (server_addr_.IsUnresolved()) {
|
||||||
ResolveStunAddress();
|
ResolveStunAddress();
|
||||||
} else if (socket_->GetState() == talk_base::AsyncPacketSocket::STATE_BOUND) {
|
} else if (socket_->GetState() == talk_base::AsyncPacketSocket::STATE_BOUND) {
|
||||||
if (server_addr_.family() == ip().family()) {
|
// Check if |server_addr_| is compatible with the port's ip.
|
||||||
|
if (IsCompatibleAddress(server_addr_)) {
|
||||||
requests_.Send(new StunBindingRequest(this, true, server_addr_));
|
requests_.Send(new StunBindingRequest(this, true, server_addr_));
|
||||||
|
} else {
|
||||||
|
// Since we can't send stun messages to the server, we should mark this
|
||||||
|
// port ready.
|
||||||
|
OnStunBindingOrResolveRequestFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,7 @@ class TestTurnServer : public TurnAuthInterface {
|
|||||||
const talk_base::SocketAddress& udp_int_addr,
|
const talk_base::SocketAddress& udp_int_addr,
|
||||||
const talk_base::SocketAddress& udp_ext_addr)
|
const talk_base::SocketAddress& udp_ext_addr)
|
||||||
: server_(thread) {
|
: server_(thread) {
|
||||||
server_.AddInternalSocket(talk_base::AsyncUDPSocket::Create(
|
AddInternalSocket(udp_int_addr, cricket::PROTO_UDP);
|
||||||
thread->socketserver(), udp_int_addr), PROTO_UDP);
|
|
||||||
server_.SetExternalSocketFactory(new talk_base::BasicPacketSocketFactory(),
|
server_.SetExternalSocketFactory(new talk_base::BasicPacketSocketFactory(),
|
||||||
udp_ext_addr);
|
udp_ext_addr);
|
||||||
server_.set_realm(kTestRealm);
|
server_.set_realm(kTestRealm);
|
||||||
@ -62,6 +61,23 @@ class TestTurnServer : public TurnAuthInterface {
|
|||||||
|
|
||||||
TurnServer* server() { return &server_; }
|
TurnServer* server() { return &server_; }
|
||||||
|
|
||||||
|
void AddInternalSocket(const talk_base::SocketAddress& int_addr,
|
||||||
|
ProtocolType proto) {
|
||||||
|
talk_base::Thread* thread = talk_base::Thread::Current();
|
||||||
|
if (proto == cricket::PROTO_UDP) {
|
||||||
|
server_.AddInternalSocket(talk_base::AsyncUDPSocket::Create(
|
||||||
|
thread->socketserver(), int_addr), proto);
|
||||||
|
} else if (proto == cricket::PROTO_TCP) {
|
||||||
|
// For TCP we need to create a server socket which can listen for incoming
|
||||||
|
// new connections.
|
||||||
|
talk_base::AsyncSocket* socket =
|
||||||
|
thread->socketserver()->CreateAsyncSocket(SOCK_STREAM);
|
||||||
|
socket->Bind(int_addr);
|
||||||
|
socket->Listen(5);
|
||||||
|
server_.AddInternalServerSocket(socket, proto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For this test server, succeed if the password is the same as the username.
|
// For this test server, succeed if the password is the same as the username.
|
||||||
// Obviously, do not use this in a production environment.
|
// Obviously, do not use this in a production environment.
|
||||||
|
@ -206,6 +206,14 @@ void TurnPort::PrepareAddress() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If protocol family of server address doesn't match with local, return.
|
||||||
|
if (!IsCompatibleAddress(server_address_.address)) {
|
||||||
|
LOG(LS_ERROR) << "Server IP address family does not match with "
|
||||||
|
<< "local host address family type";
|
||||||
|
OnAllocateError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!server_address_.address.port()) {
|
if (!server_address_.address.port()) {
|
||||||
// We will set default TURN port, if no port is set in the address.
|
// We will set default TURN port, if no port is set in the address.
|
||||||
server_address_.address.SetPort(TURN_DEFAULT_PORT);
|
server_address_.address.SetPort(TURN_DEFAULT_PORT);
|
||||||
|
@ -53,11 +53,17 @@ using cricket::UDPPort;
|
|||||||
|
|
||||||
static const SocketAddress kLocalAddr1("11.11.11.11", 0);
|
static const SocketAddress kLocalAddr1("11.11.11.11", 0);
|
||||||
static const SocketAddress kLocalAddr2("22.22.22.22", 0);
|
static const SocketAddress kLocalAddr2("22.22.22.22", 0);
|
||||||
|
static const SocketAddress kLocalIPv6Addr(
|
||||||
|
"2401:fa00:4:1000:be30:5bff:fee5:c3", 0);
|
||||||
static const SocketAddress kTurnUdpIntAddr("99.99.99.3",
|
static const SocketAddress kTurnUdpIntAddr("99.99.99.3",
|
||||||
cricket::TURN_SERVER_PORT);
|
cricket::TURN_SERVER_PORT);
|
||||||
static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
|
static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
|
||||||
cricket::TURN_SERVER_PORT);
|
cricket::TURN_SERVER_PORT);
|
||||||
static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
|
static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
|
||||||
|
static const SocketAddress kTurnUdpIPv6IntAddr(
|
||||||
|
"2400:4030:1:2c00:be30:abcd:efab:cdef", cricket::TURN_SERVER_PORT);
|
||||||
|
static const SocketAddress kTurnUdpIPv6ExtAddr(
|
||||||
|
"2620:0:1000:1b03:2e41:38ff:fea6:f2a4", 0);
|
||||||
|
|
||||||
static const char kIceUfrag1[] = "TESTICEUFRAG0001";
|
static const char kIceUfrag1[] = "TESTICEUFRAG0001";
|
||||||
static const char kIceUfrag2[] = "TESTICEUFRAG0002";
|
static const char kIceUfrag2[] = "TESTICEUFRAG0002";
|
||||||
@ -71,6 +77,8 @@ static const cricket::ProtocolAddress kTurnUdpProtoAddr(
|
|||||||
kTurnUdpIntAddr, cricket::PROTO_UDP);
|
kTurnUdpIntAddr, cricket::PROTO_UDP);
|
||||||
static const cricket::ProtocolAddress kTurnTcpProtoAddr(
|
static const cricket::ProtocolAddress kTurnTcpProtoAddr(
|
||||||
kTurnTcpIntAddr, cricket::PROTO_TCP);
|
kTurnTcpIntAddr, cricket::PROTO_TCP);
|
||||||
|
static const cricket::ProtocolAddress kTurnUdpIPv6ProtoAddr(
|
||||||
|
kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
|
||||||
|
|
||||||
class TurnPortTest : public testing::Test,
|
class TurnPortTest : public testing::Test,
|
||||||
public sigslot::has_slots<> {
|
public sigslot::has_slots<> {
|
||||||
@ -130,9 +138,15 @@ class TurnPortTest : public testing::Test,
|
|||||||
void CreateTurnPort(const std::string& username,
|
void CreateTurnPort(const std::string& username,
|
||||||
const std::string& password,
|
const std::string& password,
|
||||||
const cricket::ProtocolAddress& server_address) {
|
const cricket::ProtocolAddress& server_address) {
|
||||||
|
CreateTurnPort(kLocalAddr1, username, password, server_address);
|
||||||
|
}
|
||||||
|
void CreateTurnPort(const talk_base::SocketAddress& local_address,
|
||||||
|
const std::string& username,
|
||||||
|
const std::string& password,
|
||||||
|
const cricket::ProtocolAddress& server_address) {
|
||||||
cricket::RelayCredentials credentials(username, password);
|
cricket::RelayCredentials credentials(username, password);
|
||||||
turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
|
turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
|
||||||
kLocalAddr1.ipaddr(), 0, 0,
|
local_address.ipaddr(), 0, 0,
|
||||||
kIceUfrag1, kIcePwd1,
|
kIceUfrag1, kIcePwd1,
|
||||||
server_address, credentials));
|
server_address, credentials));
|
||||||
turn_port_->SignalPortComplete.connect(this,
|
turn_port_->SignalPortComplete.connect(this,
|
||||||
@ -265,10 +279,7 @@ TEST_F(TurnPortTest, TestTurnAllocate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TurnPortTest, TestTurnTcpAllocate) {
|
TEST_F(TurnPortTest, TestTurnTcpAllocate) {
|
||||||
talk_base::AsyncSocket* tcp_server_socket =
|
turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
|
||||||
CreateServerSocket(kTurnTcpIntAddr);
|
|
||||||
turn_server_.server()->AddInternalServerSocket(
|
|
||||||
tcp_server_socket, cricket::PROTO_TCP);
|
|
||||||
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
||||||
EXPECT_EQ(0, turn_port_->SetOption(talk_base::Socket::OPT_SNDBUF, 10*1024));
|
EXPECT_EQ(0, turn_port_->SetOption(talk_base::Socket::OPT_SNDBUF, 10*1024));
|
||||||
turn_port_->PrepareAddress();
|
turn_port_->PrepareAddress();
|
||||||
@ -298,10 +309,7 @@ TEST_F(TurnPortTest, TestTurnConnection) {
|
|||||||
|
|
||||||
// Test that we can establish a TCP connection with TURN server.
|
// Test that we can establish a TCP connection with TURN server.
|
||||||
TEST_F(TurnPortTest, TestTurnTcpConnection) {
|
TEST_F(TurnPortTest, TestTurnTcpConnection) {
|
||||||
talk_base::AsyncSocket* tcp_server_socket =
|
turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
|
||||||
CreateServerSocket(kTurnTcpIntAddr);
|
|
||||||
turn_server_.server()->AddInternalServerSocket(
|
|
||||||
tcp_server_socket, cricket::PROTO_TCP);
|
|
||||||
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
||||||
TestTurnConnection();
|
TestTurnConnection();
|
||||||
}
|
}
|
||||||
@ -327,19 +335,44 @@ TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) {
|
|||||||
TestTurnConnection();
|
TestTurnConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a TURN allocation, establish a connection, and send some data.
|
// Do a TURN allocation, establish a UDP connection, and send some data.
|
||||||
TEST_F(TurnPortTest, TestTurnSendDataTurnUdpToUdp) {
|
TEST_F(TurnPortTest, TestTurnSendDataTurnUdpToUdp) {
|
||||||
// Create ports and prepare addresses.
|
// Create ports and prepare addresses.
|
||||||
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
|
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
|
||||||
TestTurnSendData();
|
TestTurnSendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do a TURN allocation, establish a TCP connection, and send some data.
|
||||||
TEST_F(TurnPortTest, TestTurnSendDataTurnTcpToUdp) {
|
TEST_F(TurnPortTest, TestTurnSendDataTurnTcpToUdp) {
|
||||||
talk_base::AsyncSocket* tcp_server_socket =
|
turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
|
||||||
CreateServerSocket(kTurnTcpIntAddr);
|
|
||||||
turn_server_.server()->AddInternalServerSocket(
|
|
||||||
tcp_server_socket, cricket::PROTO_TCP);
|
|
||||||
// Create ports and prepare addresses.
|
// Create ports and prepare addresses.
|
||||||
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
||||||
TestTurnSendData();
|
TestTurnSendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test TURN fails to make a connection from IPv6 address to a server which has
|
||||||
|
// IPv4 address.
|
||||||
|
TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv4) {
|
||||||
|
turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
|
||||||
|
CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
|
||||||
|
kTurnUdpProtoAddr);
|
||||||
|
turn_port_->PrepareAddress();
|
||||||
|
ASSERT_TRUE_WAIT(turn_error_, kTimeout);
|
||||||
|
EXPECT_TRUE(turn_port_->Candidates().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test TURN make a connection from IPv6 address to a server which has
|
||||||
|
// IPv6 intenal address. But in this test external address is a IPv4 address,
|
||||||
|
// hence allocated address will be a IPv4 address.
|
||||||
|
TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv6ExtenalIPv4) {
|
||||||
|
turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
|
||||||
|
CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
|
||||||
|
kTurnUdpIPv6ProtoAddr);
|
||||||
|
turn_port_->PrepareAddress();
|
||||||
|
EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
|
||||||
|
ASSERT_EQ(1U, turn_port_->Candidates().size());
|
||||||
|
EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
|
||||||
|
turn_port_->Candidates()[0].address().ipaddr());
|
||||||
|
EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -708,7 +708,7 @@ AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
|
|||||||
config_(config),
|
config_(config),
|
||||||
state_(kInit),
|
state_(kInit),
|
||||||
flags_(flags),
|
flags_(flags),
|
||||||
udp_socket_(NULL),
|
udp_socket_(),
|
||||||
phase_(0) {
|
phase_(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class FakePortAllocatorSession : public PortAllocatorSession {
|
|||||||
factory_(factory),
|
factory_(factory),
|
||||||
network_("network", "unittest",
|
network_("network", "unittest",
|
||||||
talk_base::IPAddress(INADDR_LOOPBACK), 8),
|
talk_base::IPAddress(INADDR_LOOPBACK), 8),
|
||||||
port_(NULL), running_(false),
|
port_(), running_(false),
|
||||||
port_config_count_(0) {
|
port_config_count_(0) {
|
||||||
network_.AddIP(talk_base::IPAddress(INADDR_LOOPBACK));
|
network_.AddIP(talk_base::IPAddress(INADDR_LOOPBACK));
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,8 @@ using talk_base::SocketAddress;
|
|||||||
using talk_base::Thread;
|
using talk_base::Thread;
|
||||||
|
|
||||||
static const SocketAddress kClientAddr("11.11.11.11", 0);
|
static const SocketAddress kClientAddr("11.11.11.11", 0);
|
||||||
|
static const SocketAddress kClientIPv6Addr(
|
||||||
|
"2401:fa00:4:1000:be30:5bff:fee5:c3", 0);
|
||||||
static const SocketAddress kNatAddr("77.77.77.77", talk_base::NAT_SERVER_PORT);
|
static const SocketAddress kNatAddr("77.77.77.77", talk_base::NAT_SERVER_PORT);
|
||||||
static const SocketAddress kRemoteClientAddr("22.22.22.22", 0);
|
static const SocketAddress kRemoteClientAddr("22.22.22.22", 0);
|
||||||
static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
|
static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
|
||||||
@ -740,6 +742,36 @@ TEST_F(PortAllocatorTest, TestEnableSharedSocketNoUdpAllowed) {
|
|||||||
EXPECT_EQ(1U, candidates_.size());
|
EXPECT_EQ(1U, candidates_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies allocator can use IPv6 addresses along with IPv4.
|
||||||
|
TEST_F(PortAllocatorTest, TestEnableIPv6Addresses) {
|
||||||
|
allocator().set_flags(allocator().flags() |
|
||||||
|
cricket::PORTALLOCATOR_DISABLE_RELAY |
|
||||||
|
cricket::PORTALLOCATOR_ENABLE_IPV6 |
|
||||||
|
cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
|
||||||
|
cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET);
|
||||||
|
AddInterface(kClientIPv6Addr);
|
||||||
|
AddInterface(kClientAddr);
|
||||||
|
allocator_->set_step_delay(cricket::kMinimumStepDelay);
|
||||||
|
EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
|
||||||
|
session_->StartGettingPorts();
|
||||||
|
ASSERT_EQ_WAIT(4U, ports_.size(), kDefaultAllocationTimeout);
|
||||||
|
EXPECT_EQ(4U, candidates_.size());
|
||||||
|
EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout);
|
||||||
|
EXPECT_PRED5(CheckCandidate, candidates_[0],
|
||||||
|
cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp",
|
||||||
|
kClientIPv6Addr);
|
||||||
|
EXPECT_PRED5(CheckCandidate, candidates_[1],
|
||||||
|
cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp",
|
||||||
|
kClientAddr);
|
||||||
|
EXPECT_PRED5(CheckCandidate, candidates_[2],
|
||||||
|
cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp",
|
||||||
|
kClientIPv6Addr);
|
||||||
|
EXPECT_PRED5(CheckCandidate, candidates_[3],
|
||||||
|
cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp",
|
||||||
|
kClientAddr);
|
||||||
|
EXPECT_EQ(4U, candidates_.size());
|
||||||
|
}
|
||||||
|
|
||||||
// Test that the httpportallocator correctly maintains its lists of stun and
|
// Test that the httpportallocator correctly maintains its lists of stun and
|
||||||
// relay servers, by never allowing an empty list.
|
// relay servers, by never allowing an empty list.
|
||||||
TEST(HttpPortAllocatorTest, TestHttpPortAllocatorHostLists) {
|
TEST(HttpPortAllocatorTest, TestHttpPortAllocatorHostLists) {
|
||||||
|
@ -399,7 +399,6 @@ BaseChannel::BaseChannel(talk_base::Thread* thread,
|
|||||||
writable_(false),
|
writable_(false),
|
||||||
rtp_ready_to_send_(false),
|
rtp_ready_to_send_(false),
|
||||||
rtcp_ready_to_send_(false),
|
rtcp_ready_to_send_(false),
|
||||||
optimistic_data_send_(false),
|
|
||||||
was_ever_writable_(false),
|
was_ever_writable_(false),
|
||||||
local_content_direction_(MD_INACTIVE),
|
local_content_direction_(MD_INACTIVE),
|
||||||
remote_content_direction_(MD_INACTIVE),
|
remote_content_direction_(MD_INACTIVE),
|
||||||
@ -670,7 +669,7 @@ bool BaseChannel::SendPacket(bool rtcp, talk_base::Buffer* packet,
|
|||||||
// transport.
|
// transport.
|
||||||
TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
|
TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
|
||||||
transport_channel_ : rtcp_transport_channel_;
|
transport_channel_ : rtcp_transport_channel_;
|
||||||
if (!channel || (!optimistic_data_send_ && !channel->writable())) {
|
if (!channel || !channel->writable()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,10 +97,6 @@ class BaseChannel
|
|||||||
return rtcp_transport_channel_;
|
return rtcp_transport_channel_;
|
||||||
}
|
}
|
||||||
bool enabled() const { return enabled_; }
|
bool enabled() const { return enabled_; }
|
||||||
// Set to true to have the channel optimistically allow data to be sent even
|
|
||||||
// when the channel isn't fully writable.
|
|
||||||
void set_optimistic_data_send(bool value) { optimistic_data_send_ = value; }
|
|
||||||
bool optimistic_data_send() const { return optimistic_data_send_; }
|
|
||||||
|
|
||||||
// This function returns true if we are using SRTP.
|
// This function returns true if we are using SRTP.
|
||||||
bool secure() const { return srtp_filter_.IsActive(); }
|
bool secure() const { return srtp_filter_.IsActive(); }
|
||||||
@ -362,7 +358,6 @@ class BaseChannel
|
|||||||
bool writable_;
|
bool writable_;
|
||||||
bool rtp_ready_to_send_;
|
bool rtp_ready_to_send_;
|
||||||
bool rtcp_ready_to_send_;
|
bool rtcp_ready_to_send_;
|
||||||
bool optimistic_data_send_;
|
|
||||||
bool was_ever_writable_;
|
bool was_ever_writable_;
|
||||||
MediaContentDirection local_content_direction_;
|
MediaContentDirection local_content_direction_;
|
||||||
MediaContentDirection remote_content_direction_;
|
MediaContentDirection remote_content_direction_;
|
||||||
|
@ -496,11 +496,6 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
|||||||
// overridden in specialized classes
|
// overridden in specialized classes
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOptimisticDataSend(bool optimistic_data_send) {
|
|
||||||
channel1_->set_optimistic_data_send(optimistic_data_send);
|
|
||||||
channel2_->set_optimistic_data_send(optimistic_data_send);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a cricket::SessionDescription with one MediaContent and one stream.
|
// Creates a cricket::SessionDescription with one MediaContent and one stream.
|
||||||
// kPcmuCodec is used as audio codec and kH264Codec is used as video codec.
|
// kPcmuCodec is used as audio codec and kH264Codec is used as video codec.
|
||||||
cricket::SessionDescription* CreateSessionDescriptionWithStream(uint32 ssrc) {
|
cricket::SessionDescription* CreateSessionDescriptionWithStream(uint32 ssrc) {
|
||||||
@ -1394,19 +1389,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
|||||||
EXPECT_TRUE(CheckNoRtp1());
|
EXPECT_TRUE(CheckNoRtp1());
|
||||||
EXPECT_TRUE(CheckNoRtp2());
|
EXPECT_TRUE(CheckNoRtp2());
|
||||||
|
|
||||||
// Lose writability, with optimistic send
|
// Lose writability, which should fail.
|
||||||
SetOptimisticDataSend(true);
|
|
||||||
GetTransport1()->SetWritable(false);
|
GetTransport1()->SetWritable(false);
|
||||||
EXPECT_TRUE(media_channel1_->sending());
|
|
||||||
EXPECT_TRUE(SendRtp1());
|
|
||||||
EXPECT_TRUE(SendRtp2());
|
|
||||||
EXPECT_TRUE(CheckRtp1());
|
|
||||||
EXPECT_TRUE(CheckRtp2());
|
|
||||||
EXPECT_TRUE(CheckNoRtp1());
|
|
||||||
EXPECT_TRUE(CheckNoRtp2());
|
|
||||||
|
|
||||||
// Check again with optimistic send off, which should fail.
|
|
||||||
SetOptimisticDataSend(false);
|
|
||||||
EXPECT_FALSE(SendRtp1());
|
EXPECT_FALSE(SendRtp1());
|
||||||
EXPECT_TRUE(SendRtp2());
|
EXPECT_TRUE(SendRtp2());
|
||||||
EXPECT_TRUE(CheckRtp1());
|
EXPECT_TRUE(CheckRtp1());
|
||||||
@ -1426,13 +1410,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
|||||||
GetTransport1()->SetDestination(NULL);
|
GetTransport1()->SetDestination(NULL);
|
||||||
EXPECT_TRUE(media_channel1_->sending());
|
EXPECT_TRUE(media_channel1_->sending());
|
||||||
|
|
||||||
// Should fail regardless of optimistic send at this point.
|
// Should fail also.
|
||||||
SetOptimisticDataSend(true);
|
|
||||||
EXPECT_FALSE(SendRtp1());
|
|
||||||
EXPECT_TRUE(SendRtp2());
|
|
||||||
EXPECT_TRUE(CheckRtp1());
|
|
||||||
EXPECT_TRUE(CheckNoRtp2());
|
|
||||||
SetOptimisticDataSend(false);
|
|
||||||
EXPECT_FALSE(SendRtp1());
|
EXPECT_FALSE(SendRtp1());
|
||||||
EXPECT_TRUE(SendRtp2());
|
EXPECT_TRUE(SendRtp2());
|
||||||
EXPECT_TRUE(CheckRtp1());
|
EXPECT_TRUE(CheckRtp1());
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
#ifdef HAVE_SCTP
|
#ifdef HAVE_SCTP
|
||||||
#include "talk/media/sctp/sctpdataengine.h"
|
#include "talk/media/sctp/sctpdataengine.h"
|
||||||
#else
|
#else
|
||||||
static const uint32 kMaxSctpSid = USHRT_MAX;
|
static const uint32 kMaxSctpSid = 1023;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -882,8 +882,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
|
|||||||
answer_opts.data_channel_type = cricket::DCT_RTP;
|
answer_opts.data_channel_type = cricket::DCT_RTP;
|
||||||
offer_opts.data_channel_type = cricket::DCT_RTP;
|
offer_opts.data_channel_type = cricket::DCT_RTP;
|
||||||
|
|
||||||
talk_base::scoped_ptr<SessionDescription> offer(NULL);
|
talk_base::scoped_ptr<SessionDescription> offer;
|
||||||
talk_base::scoped_ptr<SessionDescription> answer(NULL);
|
talk_base::scoped_ptr<SessionDescription> answer;
|
||||||
|
|
||||||
offer_opts.rtcp_mux_enabled = true;
|
offer_opts.rtcp_mux_enabled = true;
|
||||||
answer_opts.rtcp_mux_enabled = true;
|
answer_opts.rtcp_mux_enabled = true;
|
||||||
|
@ -342,7 +342,7 @@ class AlsaInputStream :
|
|||||||
}
|
}
|
||||||
|
|
||||||
AlsaStream stream_;
|
AlsaStream stream_;
|
||||||
talk_base::scoped_array<char> buffer_;
|
talk_base::scoped_ptr<char[]> buffer_;
|
||||||
size_t buffer_size_;
|
size_t buffer_size_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(AlsaInputStream);
|
DISALLOW_COPY_AND_ASSIGN(AlsaInputStream);
|
||||||
|
@ -37,7 +37,7 @@ namespace buzz {
|
|||||||
|
|
||||||
XmlBuilder::XmlBuilder() :
|
XmlBuilder::XmlBuilder() :
|
||||||
pelCurrent_(NULL),
|
pelCurrent_(NULL),
|
||||||
pelRoot_(NULL),
|
pelRoot_(),
|
||||||
pvParents_(new std::vector<XmlElement *>()) {
|
pvParents_(new std::vector<XmlElement *>()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@ public:
|
|||||||
|
|
||||||
explicit Private(XmppClient* client) :
|
explicit Private(XmppClient* client) :
|
||||||
client_(client),
|
client_(client),
|
||||||
socket_(NULL),
|
socket_(),
|
||||||
engine_(NULL),
|
engine_(),
|
||||||
proxy_port_(0),
|
proxy_port_(0),
|
||||||
pre_engine_error_(XmppEngine::ERROR_NONE),
|
pre_engine_error_(XmppEngine::ERROR_NONE),
|
||||||
pre_engine_subcode_(0),
|
pre_engine_subcode_(0),
|
||||||
|
@ -58,12 +58,12 @@ XmppEngineImpl::XmppEngineImpl()
|
|||||||
encrypted_(false),
|
encrypted_(false),
|
||||||
error_code_(ERROR_NONE),
|
error_code_(ERROR_NONE),
|
||||||
subcode_(0),
|
subcode_(0),
|
||||||
stream_error_(NULL),
|
stream_error_(),
|
||||||
raised_reset_(false),
|
raised_reset_(false),
|
||||||
output_handler_(NULL),
|
output_handler_(NULL),
|
||||||
session_handler_(NULL),
|
session_handler_(NULL),
|
||||||
iq_entries_(new IqEntryVector()),
|
iq_entries_(new IqEntryVector()),
|
||||||
sasl_handler_(NULL),
|
sasl_handler_(),
|
||||||
output_(new std::stringstream()) {
|
output_(new std::stringstream()) {
|
||||||
for (int i = 0; i < HL_COUNT; i+= 1) {
|
for (int i = 0; i < HL_COUNT; i+= 1) {
|
||||||
stanza_handlers_[i].reset(new StanzaHandlerVector());
|
stanza_handlers_[i].reset(new StanzaHandlerVector());
|
||||||
|
@ -66,11 +66,11 @@ XmppLoginTask::XmppLoginTask(XmppEngineImpl * pctx) :
|
|||||||
pelStanza_(NULL),
|
pelStanza_(NULL),
|
||||||
isStart_(false),
|
isStart_(false),
|
||||||
iqId_(STR_EMPTY),
|
iqId_(STR_EMPTY),
|
||||||
pelFeatures_(NULL),
|
pelFeatures_(),
|
||||||
fullJid_(STR_EMPTY),
|
fullJid_(STR_EMPTY),
|
||||||
streamId_(STR_EMPTY),
|
streamId_(STR_EMPTY),
|
||||||
pvecQueuedStanzas_(new std::vector<XmlElement *>()),
|
pvecQueuedStanzas_(new std::vector<XmlElement *>()),
|
||||||
sasl_mech_(NULL) {
|
sasl_mech_() {
|
||||||
}
|
}
|
||||||
|
|
||||||
XmppLoginTask::~XmppLoginTask() {
|
XmppLoginTask::~XmppLoginTask() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user