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",
|
||||
|
||||
"third_party/libyuv":
|
||||
(Var("googlecode_url") % "libyuv") + "/trunk@723",
|
||||
(Var("googlecode_url") % "libyuv") + "/trunk@826",
|
||||
|
||||
"third_party/opus":
|
||||
Var("chromium_trunk") + "/src/third_party/opus@185405",
|
||||
|
@ -53,7 +53,9 @@ const char MediaConstraintsInterface::kHighpassFilter[] =
|
||||
"googHighpassFilter";
|
||||
const char MediaConstraintsInterface::kTypingNoiseDetection[] =
|
||||
"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 {
|
||||
|
||||
@ -90,10 +92,10 @@ bool FromConstraints(const MediaConstraintsInterface::Constraints& constraints,
|
||||
options->noise_suppression.Set(value);
|
||||
else if (iter->key == MediaConstraintsInterface::kHighpassFilter)
|
||||
options->highpass_filter.Set(value);
|
||||
else if (iter->key == MediaConstraintsInterface::kInternalAecDump)
|
||||
options->aec_dump.Set(value);
|
||||
else if (iter->key == MediaConstraintsInterface::kTypingNoiseDetection)
|
||||
options->typing_detection.Set(value);
|
||||
else if (iter->key == MediaConstraintsInterface::kAudioMirroring)
|
||||
options->stereo_swapping.Set(value);
|
||||
else
|
||||
success = false;
|
||||
}
|
||||
@ -103,14 +105,16 @@ bool FromConstraints(const MediaConstraintsInterface::Constraints& constraints,
|
||||
} // namespace
|
||||
|
||||
talk_base::scoped_refptr<LocalAudioSource> LocalAudioSource::Create(
|
||||
const PeerConnectionFactoryInterface::Options& options,
|
||||
const MediaConstraintsInterface* constraints) {
|
||||
talk_base::scoped_refptr<LocalAudioSource> source(
|
||||
new talk_base::RefCountedObject<LocalAudioSource>());
|
||||
source->Initialize(constraints);
|
||||
source->Initialize(options, constraints);
|
||||
return source;
|
||||
}
|
||||
|
||||
void LocalAudioSource::Initialize(
|
||||
const PeerConnectionFactoryInterface::Options& options,
|
||||
const MediaConstraintsInterface* constraints) {
|
||||
if (!constraints)
|
||||
return;
|
||||
@ -119,12 +123,14 @@ void LocalAudioSource::Initialize(
|
||||
// constraints.
|
||||
FromConstraints(constraints->GetOptional(), &options_);
|
||||
|
||||
cricket::AudioOptions options;
|
||||
if (!FromConstraints(constraints->GetMandatory(), &options)) {
|
||||
cricket::AudioOptions audio_options;
|
||||
if (!FromConstraints(constraints->GetMandatory(), &audio_options)) {
|
||||
source_state_ = kEnded;
|
||||
return;
|
||||
}
|
||||
options_.SetAll(options);
|
||||
options_.SetAll(audio_options);
|
||||
if (options.enable_aec_dump)
|
||||
options_.aec_dump.Set(true);
|
||||
source_state_ = kLive;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "talk/app/webrtc/mediastreaminterface.h"
|
||||
#include "talk/app/webrtc/notifier.h"
|
||||
#include "talk/app/webrtc/peerconnectioninterface.h"
|
||||
#include "talk/base/scoped_ptr.h"
|
||||
#include "talk/media/base/mediachannel.h"
|
||||
|
||||
@ -44,6 +45,7 @@ class LocalAudioSource : public Notifier<AudioSourceInterface> {
|
||||
public:
|
||||
// Creates an instance of LocalAudioSource.
|
||||
static talk_base::scoped_refptr<LocalAudioSource> Create(
|
||||
const PeerConnectionFactoryInterface::Options& options,
|
||||
const MediaConstraintsInterface* constraints);
|
||||
|
||||
virtual SourceState state() const { return source_state_; }
|
||||
@ -58,7 +60,8 @@ class LocalAudioSource : public Notifier<AudioSourceInterface> {
|
||||
}
|
||||
|
||||
private:
|
||||
void Initialize(const MediaConstraintsInterface* constraints);
|
||||
void Initialize(const PeerConnectionFactoryInterface::Options& options,
|
||||
const MediaConstraintsInterface* constraints);
|
||||
|
||||
cricket::AudioOptions options_;
|
||||
SourceState source_state_;
|
||||
|
@ -39,6 +39,7 @@
|
||||
using webrtc::LocalAudioSource;
|
||||
using webrtc::MediaConstraintsInterface;
|
||||
using webrtc::MediaSourceInterface;
|
||||
using webrtc::PeerConnectionFactoryInterface;
|
||||
|
||||
TEST(LocalAudioSourceTest, SetValidOptions) {
|
||||
webrtc::FakeConstraints constraints;
|
||||
@ -52,7 +53,8 @@ TEST(LocalAudioSourceTest, SetValidOptions) {
|
||||
constraints.AddOptional(MediaConstraintsInterface::kHighpassFilter, true);
|
||||
|
||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||
LocalAudioSource::Create(&constraints);
|
||||
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||
&constraints);
|
||||
|
||||
bool value;
|
||||
EXPECT_TRUE(source->options().echo_cancellation.Get(&value));
|
||||
@ -72,7 +74,8 @@ TEST(LocalAudioSourceTest, SetValidOptions) {
|
||||
TEST(LocalAudioSourceTest, OptionNotSet) {
|
||||
webrtc::FakeConstraints constraints;
|
||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||
LocalAudioSource::Create(&constraints);
|
||||
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||
&constraints);
|
||||
bool value;
|
||||
EXPECT_FALSE(source->options().highpass_filter.Get(&value));
|
||||
}
|
||||
@ -83,7 +86,8 @@ TEST(LocalAudioSourceTest, MandatoryOverridesOptional) {
|
||||
constraints.AddOptional(MediaConstraintsInterface::kEchoCancellation, true);
|
||||
|
||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||
LocalAudioSource::Create(&constraints);
|
||||
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||
&constraints);
|
||||
|
||||
bool value;
|
||||
EXPECT_TRUE(source->options().echo_cancellation.Get(&value));
|
||||
@ -96,7 +100,8 @@ TEST(LocalAudioSourceTest, InvalidOptional) {
|
||||
constraints.AddOptional("invalidKey", false);
|
||||
|
||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||
LocalAudioSource::Create(&constraints);
|
||||
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||
&constraints);
|
||||
|
||||
EXPECT_EQ(MediaSourceInterface::kLive, source->state());
|
||||
bool value;
|
||||
@ -110,7 +115,8 @@ TEST(LocalAudioSourceTest, InvalidMandatory) {
|
||||
constraints.AddMandatory("invalidKey", false);
|
||||
|
||||
talk_base::scoped_refptr<LocalAudioSource> source =
|
||||
LocalAudioSource::Create(&constraints);
|
||||
LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
|
||||
&constraints);
|
||||
|
||||
EXPECT_EQ(MediaSourceInterface::kEnded, source->state());
|
||||
bool value;
|
||||
|
@ -81,6 +81,7 @@ class MediaConstraintsInterface {
|
||||
static const char kNoiseSuppression[]; // googNoiseSuppression
|
||||
static const char kHighpassFilter[]; // googHighpassFilter
|
||||
static const char kTypingNoiseDetection[]; // googTypingNoiseDetection
|
||||
static const char kAudioMirroring[]; // googAudioMirroring
|
||||
|
||||
// Google-specific constraint keys for a local video source
|
||||
static const char kNoiseReduction[]; // googNoiseReduction
|
||||
@ -106,6 +107,8 @@ class MediaConstraintsInterface {
|
||||
static const char kEnableDtlsSrtp[]; // Enable DTLS-SRTP
|
||||
// Temporary pseudo-constraints used to enable DataChannels
|
||||
static const char kEnableRtpDataChannels[]; // Enable RTP DataChannels
|
||||
// TODO(perkj): Remove kEnableSctpDataChannels once Chrome use
|
||||
// PeerConnectionFactory::SetOptions.
|
||||
static const char kEnableSctpDataChannels[]; // Enable SCTP DataChannels
|
||||
|
||||
// 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
|
||||
// removed.
|
||||
// Used by a local audio source.
|
||||
// TODO(perkj): Remove once Chrome use PeerConnectionFactory::SetOptions.
|
||||
static const char kInternalAecDump[]; // internalAecDump
|
||||
// Used for disabling security and use plain RTP.
|
||||
static const char kInternalDisableEncryption[]; // internalDisableEncryption
|
||||
|
||||
protected:
|
||||
// Dtor protected as objects shouldn't be deleted via this interface
|
||||
|
@ -267,6 +267,10 @@ bool MediaStreamSignaling::AddDataChannelFromOpenMessage(
|
||||
}
|
||||
scoped_refptr<DataChannel> channel(
|
||||
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;
|
||||
stream_observer_->OnAddDataChannel(channel);
|
||||
// It's immediately ready to use.
|
||||
|
@ -317,7 +317,8 @@ bool PeerConnection::DoInitialize(
|
||||
stats_.set_session(session_.get());
|
||||
|
||||
// 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;
|
||||
|
||||
// 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.
|
||||
constraints.AddMandatory(
|
||||
MediaConstraintsInterface::kHighpassFilter, false);
|
||||
talk_base::scoped_refptr<webrtc::LocalAudioSource> source =
|
||||
webrtc::LocalAudioSource::Create(&constraints);
|
||||
talk_base::scoped_refptr<webrtc::AudioSourceInterface> source =
|
||||
peer_connection_factory_->CreateAudioSource(&constraints);
|
||||
// TODO(perkj): Test audio source when it is implemented. Currently audio
|
||||
// always use the default input.
|
||||
talk_base::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
|
||||
|
@ -261,7 +261,7 @@ talk_base::scoped_refptr<AudioSourceInterface>
|
||||
PeerConnectionFactory::CreateAudioSource_s(
|
||||
const MediaConstraintsInterface* constraints) {
|
||||
talk_base::scoped_refptr<LocalAudioSource> source(
|
||||
LocalAudioSource::Create(constraints));
|
||||
LocalAudioSource::Create(options_, constraints));
|
||||
return source;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,10 @@ namespace webrtc {
|
||||
class PeerConnectionFactory : public PeerConnectionFactoryInterface,
|
||||
public talk_base::MessageHandler {
|
||||
public:
|
||||
virtual void SetOptions(const Options& options) {
|
||||
options_ = options;
|
||||
}
|
||||
|
||||
virtual talk_base::scoped_refptr<PeerConnectionInterface>
|
||||
CreatePeerConnection(
|
||||
const PeerConnectionInterface::IceServers& configuration,
|
||||
@ -77,6 +81,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface,
|
||||
virtual cricket::ChannelManager* channel_manager();
|
||||
virtual talk_base::Thread* signaling_thread();
|
||||
virtual talk_base::Thread* worker_thread();
|
||||
const Options& options() const { return options_; }
|
||||
|
||||
protected:
|
||||
PeerConnectionFactory();
|
||||
@ -109,6 +114,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface,
|
||||
bool owns_ptrs_;
|
||||
talk_base::Thread* signaling_thread_;
|
||||
talk_base::Thread* worker_thread_;
|
||||
Options options_;
|
||||
talk_base::scoped_refptr<PortAllocatorFactoryInterface> allocator_factory_;
|
||||
// External Audio device used for audio playback.
|
||||
talk_base::scoped_refptr<AudioDeviceModule> default_adm_;
|
||||
|
@ -390,6 +390,19 @@ class DTLSIdentityServiceInterface {
|
||||
// argument.
|
||||
class PeerConnectionFactoryInterface : public talk_base::RefCountInterface {
|
||||
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>
|
||||
CreatePeerConnection(
|
||||
const PeerConnectionInterface::IceServers& configuration,
|
||||
|
@ -82,6 +82,15 @@ const char StatsReport::kStatsValueNameFrameRateDecoded[] =
|
||||
"googFrameRateDecoded";
|
||||
const char StatsReport::kStatsValueNameFrameRateOutput[] =
|
||||
"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::kStatsValueNameFrameRateSent[] = "googFrameRateSent";
|
||||
const char StatsReport::kStatsValueNameFrameWidthReceived[] =
|
||||
@ -119,6 +128,7 @@ const char StatsReport::kStatsValueNameWritable[] = "googWritable";
|
||||
|
||||
const char StatsReport::kStatsReportTypeSession[] = "googLibjingleSession";
|
||||
const char StatsReport::kStatsReportTypeBwe[] = "VideoBwe";
|
||||
const char StatsReport::kStatsReportTypeRemoteSsrc[] = "remoteSsrc";
|
||||
const char StatsReport::kStatsReportTypeSsrc[] = "ssrc";
|
||||
const char StatsReport::kStatsReportTypeTrack[] = "googTrack";
|
||||
const char StatsReport::kStatsReportTypeIceCandidate[] = "iceCandidate";
|
||||
@ -241,6 +251,21 @@ void ExtractStats(const cricket::VideoReceiverInfo& info, StatsReport* report) {
|
||||
info.framerate_decoded);
|
||||
report->AddValue(StatsReport::kStatsValueNameFrameRateOutput,
|
||||
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) {
|
||||
@ -293,6 +318,18 @@ void ExtractStats(const cricket::BandwidthEstimationInfo& info,
|
||||
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) {
|
||||
return info.ssrc;
|
||||
}
|
||||
@ -319,11 +356,20 @@ void ExtractStatsFromList(const std::vector<T>& data,
|
||||
for (; it != data.end(); ++it) {
|
||||
std::string id;
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
ExtractStats(*it, report);
|
||||
if (it->remote_stats.size() > 0) {
|
||||
report = collector->PrepareRemoteReport(ssrc, transport_id);
|
||||
if (!report) {
|
||||
continue;
|
||||
}
|
||||
ExtractRemoteStats(*it, report);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -406,8 +452,9 @@ void StatsCollector::UpdateStats() {
|
||||
}
|
||||
}
|
||||
|
||||
StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
|
||||
const std::string& transport_id) {
|
||||
StatsReport* StatsCollector::PrepareLocalReport(
|
||||
uint32 ssrc,
|
||||
const std::string& transport_id) {
|
||||
std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
|
||||
StatsMap::iterator it = reports_.find(StatsId(
|
||||
StatsReport::kStatsReportTypeSsrc, ssrc_id));
|
||||
@ -427,10 +474,8 @@ StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
|
||||
&track_id);
|
||||
}
|
||||
|
||||
StatsReport* report = &reports_[
|
||||
StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id)];
|
||||
report->id = StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id);
|
||||
report->type = StatsReport::kStatsReportTypeSsrc;
|
||||
StatsReport* report = GetOrCreateReport(StatsReport::kStatsReportTypeSsrc,
|
||||
ssrc_id);
|
||||
|
||||
// Clear out stats from previous GatherStats calls if any.
|
||||
if (report->timestamp != stats_gathering_started_) {
|
||||
@ -446,6 +491,44 @@ StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
|
||||
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(
|
||||
const talk_base::SSLCertificate* cert, const std::string& issuer_id) {
|
||||
// TODO(bemasc): Move this computation to a helper class that caches these
|
||||
@ -592,6 +675,9 @@ void StatsCollector::ExtractSessionInfo() {
|
||||
info.local_candidate.address().ToString());
|
||||
report.AddValue(StatsReport::kStatsValueNameRemoteAddress,
|
||||
info.remote_candidate.address().ToString());
|
||||
report.AddValue(StatsReport::kStatsValueNameRtt, info.rtt);
|
||||
report.AddValue(StatsReport::kStatsValueNameTransportType,
|
||||
info.local_candidate.protocol());
|
||||
reports_[report.id] = report;
|
||||
}
|
||||
}
|
||||
@ -668,4 +754,19 @@ bool StatsCollector::GetTransportIdFromProxy(const std::string& proxy,
|
||||
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
|
||||
|
@ -65,9 +65,11 @@ class StatsCollector {
|
||||
// |reports|.
|
||||
bool GetStats(MediaStreamTrackInterface* track, StatsReports* reports);
|
||||
|
||||
WebRtcSession* session() { return session_; }
|
||||
// Prepare an SSRC report for the given ssrc. Used internally.
|
||||
StatsReport* PrepareReport(uint32 ssrc, const std::string& transport);
|
||||
// Prepare an SSRC report for the given ssrc. Used internally
|
||||
// in the ExtractStatsFromList template.
|
||||
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.
|
||||
bool GetTransportIdFromProxy(const std::string& proxy,
|
||||
std::string* transport_id);
|
||||
@ -88,9 +90,12 @@ class StatsCollector {
|
||||
void ExtractVideoInfo();
|
||||
double GetTimeNow();
|
||||
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.
|
||||
std::map<std::string, webrtc::StatsReport> reports_;
|
||||
std::map<std::string, StatsReport> reports_;
|
||||
// Raw pointer to the session the statistics are gathered from.
|
||||
WebRtcSession* session_;
|
||||
double stats_gathering_started_;
|
||||
|
@ -58,6 +58,10 @@ namespace {
|
||||
const char kNotFound[] = "NOT FOUND";
|
||||
const char kNoReports[] = "NO REPORTS";
|
||||
|
||||
// Constant names for track identification.
|
||||
const char kTrackId[] = "somename";
|
||||
const uint32 kSsrcOfTrack = 1234;
|
||||
|
||||
class MockWebRtcSession : public webrtc::WebRtcSession {
|
||||
public:
|
||||
explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
|
||||
@ -207,11 +211,37 @@ class StatsCollectorTest : public testing::Test {
|
||||
new cricket::ChannelManager(media_engine_,
|
||||
new cricket::FakeDeviceManager(),
|
||||
talk_base::Thread::Current())),
|
||||
session_(channel_manager_.get()) {
|
||||
session_(channel_manager_.get()),
|
||||
track_id_(kTrackId) {
|
||||
// By default, we ignore session GetStats calls.
|
||||
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,
|
||||
const std::vector<std::string>& local_ders,
|
||||
const talk_base::FakeSSLCertificate& remote_cert,
|
||||
@ -283,9 +313,14 @@ class StatsCollectorTest : public testing::Test {
|
||||
EXPECT_NE(kNotFound, remote_certificate_id);
|
||||
CheckCertChainReports(reports, remote_ders, remote_certificate_id);
|
||||
}
|
||||
|
||||
cricket::FakeMediaEngine* media_engine_;
|
||||
talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
|
||||
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.
|
||||
@ -297,17 +332,13 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
cricket::VideoSenderInfo video_sender_info;
|
||||
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.
|
||||
const int64 kBytesSent = 12345678901234LL;
|
||||
const std::string kBytesSentString("12345678901234");
|
||||
|
||||
stats.set_session(&session_);
|
||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
||||
webrtc::MediaStream::Create("streamlabel"));
|
||||
stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
|
||||
stats.AddStream(stream);
|
||||
AddVideoTrackStats();
|
||||
stats.AddStream(stream_);
|
||||
|
||||
// Construct a stats value to read.
|
||||
video_sender_info.ssrcs.push_back(1234);
|
||||
@ -319,9 +350,6 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
|
||||
EXPECT_CALL(*media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
|
||||
Return(true)));
|
||||
stats.UpdateStats();
|
||||
stats.GetStats(NULL, &reports);
|
||||
std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
|
||||
@ -339,16 +367,12 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
|
||||
cricket::VideoMediaInfo stats_read;
|
||||
// Set up an SSRC just to test that we get both kinds of stats back: SSRC and
|
||||
// BWE.
|
||||
const uint32 kSsrcOfTrack = 1234;
|
||||
const std::string kNameOfTrack("somename");
|
||||
const int64 kBytesSent = 12345678901234LL;
|
||||
const std::string kBytesSentString("12345678901234");
|
||||
|
||||
stats.set_session(&session_);
|
||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
||||
webrtc::MediaStream::Create("streamlabel"));
|
||||
stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
|
||||
stats.AddStream(stream);
|
||||
AddVideoTrackStats();
|
||||
stats.AddStream(stream_);
|
||||
|
||||
// Construct a stats value to read.
|
||||
video_sender_info.ssrcs.push_back(1234);
|
||||
@ -365,9 +389,7 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
|
||||
EXPECT_CALL(*media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
|
||||
Return(true)));
|
||||
|
||||
stats.UpdateStats();
|
||||
stats.GetStats(NULL, &reports);
|
||||
std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
|
||||
@ -417,13 +439,8 @@ TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
||||
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||
media_engine_, media_channel, &session_, "", false, NULL);
|
||||
const std::string kTrackId("somename");
|
||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
||||
webrtc::MediaStream::Create("streamlabel"));
|
||||
talk_base::scoped_refptr<webrtc::VideoTrack> track =
|
||||
webrtc::VideoTrack::Create(kTrackId, NULL);
|
||||
stream->AddTrack(track);
|
||||
stats.AddStream(stream);
|
||||
AddVideoTrackStats();
|
||||
stats.AddStream(stream_);
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
@ -449,13 +466,8 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
||||
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||
media_engine_, media_channel, &session_, "", false, NULL);
|
||||
const std::string kTrackId("somename");
|
||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
||||
webrtc::MediaStream::Create("streamlabel"));
|
||||
talk_base::scoped_refptr<webrtc::VideoTrack> track =
|
||||
webrtc::VideoTrack::Create(kTrackId, NULL);
|
||||
stream->AddTrack(track);
|
||||
stats.AddStream(stream);
|
||||
AddVideoTrackStats();
|
||||
stats.AddStream(stream_);
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
@ -464,7 +476,6 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
// Constructs an ssrc stats update.
|
||||
cricket::VideoSenderInfo video_sender_info;
|
||||
cricket::VideoMediaInfo stats_read;
|
||||
const uint32 kSsrcOfTrack = 1234;
|
||||
const int64 kBytesSent = 12345678901234LL;
|
||||
|
||||
// Construct a stats value to read.
|
||||
@ -477,23 +488,20 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
EXPECT_CALL(*media_channel, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kTrackId),
|
||||
Return(true)));
|
||||
|
||||
stats.UpdateStats();
|
||||
stats.GetStats(NULL, &reports);
|
||||
// |reports| should contain one session report, one track report, and one ssrc
|
||||
// report.
|
||||
EXPECT_EQ((size_t)3, reports.size());
|
||||
// |reports| should contain at least one session report, one track report,
|
||||
// and one ssrc report.
|
||||
EXPECT_LE((size_t)3, reports.size());
|
||||
const webrtc::StatsReport* track_report = FindNthReportByType(
|
||||
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
|
||||
EXPECT_FALSE(track_report == NULL);
|
||||
|
||||
stats.GetStats(track, &reports);
|
||||
// |reports| should contain one session report, one track report, and one ssrc
|
||||
// report.
|
||||
EXPECT_EQ((size_t)3, reports.size());
|
||||
stats.GetStats(track_, &reports);
|
||||
// |reports| should contain at least one session report, one track report,
|
||||
// and one ssrc report.
|
||||
EXPECT_LE((size_t)3, reports.size());
|
||||
track_report = FindNthReportByType(
|
||||
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
|
||||
EXPECT_FALSE(track_report == NULL);
|
||||
@ -516,13 +524,8 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||
media_engine_, media_channel, &session_, kVcName, false, NULL);
|
||||
const std::string kTrackId("somename");
|
||||
talk_base::scoped_refptr<webrtc::MediaStream> stream(
|
||||
webrtc::MediaStream::Create("streamlabel"));
|
||||
talk_base::scoped_refptr<webrtc::VideoTrack> track =
|
||||
webrtc::VideoTrack::Create(kTrackId, NULL);
|
||||
stream->AddTrack(track);
|
||||
stats.AddStream(stream);
|
||||
AddVideoTrackStats();
|
||||
stats.AddStream(stream_);
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
@ -531,7 +534,6 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
||||
// Constructs an ssrc stats update.
|
||||
cricket::VideoSenderInfo video_sender_info;
|
||||
cricket::VideoMediaInfo stats_read;
|
||||
const uint32 kSsrcOfTrack = 1234;
|
||||
const int64 kBytesSent = 12345678901234LL;
|
||||
|
||||
// Construct a stats value to read.
|
||||
@ -544,23 +546,10 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
||||
EXPECT_CALL(*media_channel, GetStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kTrackId),
|
||||
Return(true)));
|
||||
|
||||
// Instruct the session to return stats containing the transport channel.
|
||||
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;
|
||||
InitSessionStats(kVcName);
|
||||
EXPECT_CALL(session_, GetStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats),
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
|
||||
stats.UpdateStats();
|
||||
@ -575,6 +564,78 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
||||
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
|
||||
// reported
|
||||
TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
|
||||
@ -638,6 +699,7 @@ TEST_F(StatsCollectorTest, NoTransport) {
|
||||
EXPECT_CALL(session_, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
||||
Return(true)));
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(ReturnNull());
|
||||
|
||||
@ -712,5 +774,4 @@ TEST_F(StatsCollectorTest, NoCertificates) {
|
||||
ASSERT_EQ(kNotFound, remote_certificate_id);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
@ -88,6 +88,10 @@ class StatsReport {
|
||||
// The |id| field is the SSRC in decimal form of the rtp stream.
|
||||
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
|
||||
// track. The |id| field is the track id.
|
||||
static const char kStatsReportTypeTrack[];
|
||||
@ -137,6 +141,13 @@ class StatsReport {
|
||||
static const char kStatsValueNameFrameRateReceived[];
|
||||
static const char kStatsValueNameFrameRateDecoded[];
|
||||
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 kStatsValueNameFrameRateSent[];
|
||||
static const char kStatsValueNameFrameWidthReceived[];
|
||||
|
@ -119,7 +119,6 @@ class FakeConstraints : public webrtc::MediaConstraintsInterface {
|
||||
}
|
||||
|
||||
void SetAllowDtlsSctpDataChannels() {
|
||||
SetMandatory(MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
||||
SetMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true);
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,7 @@ static const char kSdpSctpDataChannelString[] =
|
||||
"a=ice-ufrag:ufrag_data\r\n"
|
||||
"a=ice-pwd:pwd_data\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[] =
|
||||
"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-pwd:pwd_data\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.
|
||||
|
@ -68,10 +68,7 @@ const char MediaConstraintsInterface::kEnableRtpDataChannels[] =
|
||||
// line flag. So it is prefixed with kInternalConstraintPrefix so JS values
|
||||
// will be removed.
|
||||
const char MediaConstraintsInterface::kEnableSctpDataChannels[] =
|
||||
"internalSctpDataChannels";
|
||||
|
||||
const char MediaConstraintsInterface::kInternalDisableEncryption[] =
|
||||
"internalDisableEncryption";
|
||||
"deprecatedSctpDataChannels";
|
||||
|
||||
// Error messages
|
||||
const char kSetLocalSdpFailed[] = "SetLocalDescription failed: ";
|
||||
@ -458,6 +455,7 @@ WebRtcSession::~WebRtcSession() {
|
||||
}
|
||||
|
||||
bool WebRtcSession::Initialize(
|
||||
const PeerConnectionFactoryInterface::Options& options,
|
||||
const MediaConstraintsInterface* constraints,
|
||||
DTLSIdentityServiceInterface* dtls_identity_service) {
|
||||
// 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.
|
||||
// It takes precendence over the kEnableSctpDataChannels constraint.
|
||||
// It takes precendence over the disable_sctp_data_channels
|
||||
// PeerConnectionFactoryInterface::Options.
|
||||
if (FindConstraint(
|
||||
constraints, MediaConstraintsInterface::kEnableRtpDataChannels,
|
||||
&value, NULL) && value) {
|
||||
LOG(LS_INFO) << "Allowing RTP data engine.";
|
||||
data_channel_type_ = cricket::DCT_RTP;
|
||||
} else {
|
||||
bool sctp_enabled = FindConstraint(
|
||||
constraints,
|
||||
MediaConstraintsInterface::kEnableSctpDataChannels,
|
||||
&value, NULL) && value;
|
||||
// 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.";
|
||||
data_channel_type_ = cricket::DCT_SCTP;
|
||||
}
|
||||
@ -520,11 +515,7 @@ bool WebRtcSession::Initialize(
|
||||
webrtc_session_desc_factory_->SignalIdentityReady.connect(
|
||||
this, &WebRtcSession::OnIdentityReady);
|
||||
|
||||
// Disable encryption if kDisableEncryption is set.
|
||||
if (FindConstraint(
|
||||
constraints,
|
||||
MediaConstraintsInterface::kInternalDisableEncryption,
|
||||
&value, NULL) && value) {
|
||||
if (options.disable_encryption) {
|
||||
webrtc_session_desc_factory_->set_secure(cricket::SEC_DISABLED);
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,8 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
MediaStreamSignaling* mediastream_signaling);
|
||||
virtual ~WebRtcSession();
|
||||
|
||||
bool Initialize(const MediaConstraintsInterface* constraints,
|
||||
bool Initialize(const PeerConnectionFactoryInterface::Options& options,
|
||||
const MediaConstraintsInterface* constraints,
|
||||
DTLSIdentityServiceInterface* dtls_identity_service);
|
||||
// Deletes the voice, video and data channel and changes the session state
|
||||
// to STATE_RECEIVEDTERMINATE.
|
||||
|
@ -81,6 +81,7 @@ using webrtc::FakeConstraints;
|
||||
using webrtc::IceCandidateCollection;
|
||||
using webrtc::JsepIceCandidate;
|
||||
using webrtc::JsepSessionDescription;
|
||||
using webrtc::PeerConnectionFactoryInterface;
|
||||
using webrtc::PeerConnectionInterface;
|
||||
using webrtc::SessionDescriptionInterface;
|
||||
using webrtc::StreamCollection;
|
||||
@ -317,7 +318,8 @@ class WebRtcSessionTest : public testing::Test {
|
||||
EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
|
||||
observer_.ice_gathering_state_);
|
||||
|
||||
EXPECT_TRUE(session_->Initialize(constraints_.get(), identity_service));
|
||||
EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
|
||||
identity_service));
|
||||
}
|
||||
|
||||
void InitWithDtmfCodec() {
|
||||
@ -919,6 +921,7 @@ class WebRtcSessionTest : public testing::Test {
|
||||
cricket::TestStunServer stun_server_;
|
||||
talk_base::FakeNetworkManager network_manager_;
|
||||
cricket::BasicPortAllocator allocator_;
|
||||
PeerConnectionFactoryInterface::Options options_;
|
||||
talk_base::scoped_ptr<FakeConstraints> constraints_;
|
||||
FakeMediaStreamSignaling mediastream_signaling_;
|
||||
talk_base::scoped_ptr<WebRtcSessionForTest> session_;
|
||||
@ -1932,9 +1935,7 @@ TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kInternalDisableEncryption, true);
|
||||
options_.disable_encryption = true;
|
||||
Init(NULL);
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
scoped_ptr<SessionDescriptionInterface> offer(
|
||||
@ -2424,9 +2425,7 @@ TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
|
||||
|
||||
// This test verifies the crypto parameter when security is disabled.
|
||||
TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kInternalDisableEncryption, true);
|
||||
options_.disable_encryption = true;
|
||||
Init(NULL);
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
talk_base::scoped_ptr<SessionDescriptionInterface> offer(
|
||||
@ -2567,8 +2566,8 @@ TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
||||
options_.disable_sctp_data_channels = false;
|
||||
|
||||
InitWithDtls(false);
|
||||
|
||||
SetLocalDescriptionWithDataChannel();
|
||||
@ -2578,9 +2577,6 @@ TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
|
||||
TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
|
||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
||||
InitWithDtls(false);
|
||||
|
||||
talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
|
||||
@ -2591,9 +2587,6 @@ TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
|
||||
TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
|
||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||
SetFactoryDtlsSrtp();
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
||||
InitWithDtls(false);
|
||||
|
||||
// Create remote offer with SCTP.
|
||||
@ -2612,8 +2605,6 @@ TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
|
||||
|
||||
TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
|
||||
InitWithDtls(false);
|
||||
@ -2625,24 +2616,26 @@ TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
|
||||
TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
|
||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
||||
InitWithDtls(false);
|
||||
|
||||
SetLocalDescriptionWithDataChannel();
|
||||
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) {
|
||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||
const int new_send_port = 9998;
|
||||
const int new_recv_port = 7775;
|
||||
|
||||
constraints_.reset(new FakeConstraints());
|
||||
constraints_->AddOptional(
|
||||
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
|
||||
|
||||
InitWithDtls(false);
|
||||
SetFactoryDtlsSrtp();
|
||||
|
||||
|
@ -79,7 +79,7 @@ class FixedSizeLockFreeQueue {
|
||||
FixedSizeLockFreeQueue() : pushed_count_(0),
|
||||
popped_count_(0),
|
||||
capacity_(0),
|
||||
data_(NULL) {}
|
||||
data_() {}
|
||||
// Constructs an empty queue with the given capacity.
|
||||
FixedSizeLockFreeQueue(size_t capacity) : pushed_count_(0),
|
||||
popped_count_(0),
|
||||
@ -157,7 +157,7 @@ class FixedSizeLockFreeQueue {
|
||||
volatile Atomic32 pushed_count_;
|
||||
volatile Atomic32 popped_count_;
|
||||
size_t capacity_;
|
||||
talk_base::scoped_array<T> data_;
|
||||
talk_base::scoped_ptr<T[]> data_;
|
||||
DISALLOW_COPY_AND_ASSIGN(FixedSizeLockFreeQueue);
|
||||
};
|
||||
|
||||
|
@ -88,7 +88,7 @@ class Buffer {
|
||||
}
|
||||
void SetCapacity(size_t 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_);
|
||||
data_.swap(data);
|
||||
capacity_ = capacity;
|
||||
@ -109,7 +109,7 @@ class Buffer {
|
||||
SetData(data, length);
|
||||
}
|
||||
|
||||
scoped_array<char> data_;
|
||||
scoped_ptr<char[]> data_;
|
||||
size_t length_;
|
||||
size_t capacity_;
|
||||
};
|
||||
|
@ -25,7 +25,7 @@
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TALK_BASE_COMMON_H_
|
||||
#ifndef TALK_BASE_COMMON_H_ // NOLINT
|
||||
#define TALK_BASE_COMMON_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 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>.
|
||||
#define stdmax(x, y) std::max(x, y)
|
||||
#else
|
||||
@ -181,9 +181,28 @@ inline bool ImplicitCastToBool(bool result) { return result; }
|
||||
#if defined(WIN32)
|
||||
#define OVERRIDE override
|
||||
#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
|
||||
#else
|
||||
#define OVERRIDE
|
||||
#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_
|
@ -2,26 +2,26 @@
|
||||
* libjingle
|
||||
* Copyright 2004--2005, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* 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,
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@ -32,7 +32,10 @@
|
||||
void operator=(const TypeName&)
|
||||
|
||||
// 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) \
|
||||
TypeName(const TypeName&); \
|
||||
DISALLOW_ASSIGN(TypeName)
|
||||
|
@ -210,7 +210,7 @@ float CpuSampler::GetSystemLoad() {
|
||||
} else {
|
||||
if (nt_query_system_information) {
|
||||
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_]);
|
||||
nt_query_system_information(
|
||||
::SystemProcessorPerformanceInformation,
|
||||
@ -281,6 +281,13 @@ float CpuSampler::GetSystemLoad() {
|
||||
const uint64 cpu_times = nice + system + user;
|
||||
const uint64 total_times = cpu_times + idle;
|
||||
#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_ = UpdateCpuLoad(total_times,
|
||||
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_usec + usage.ru_stime.tv_usec;
|
||||
#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_ = UpdateCpuLoad(total_times,
|
||||
cpu_times,
|
||||
|
@ -239,7 +239,7 @@ bool CreateRandomString(size_t len,
|
||||
const char* table, int table_size,
|
||||
std::string* str) {
|
||||
str->clear();
|
||||
scoped_array<uint8> bytes(new uint8[len]);
|
||||
scoped_ptr<uint8[]> bytes(new uint8[len]);
|
||||
if (!Rng().Generate(bytes.get(), len)) {
|
||||
LOG(LS_ERROR) << "Failed to generate random string!";
|
||||
return false;
|
||||
|
@ -43,7 +43,7 @@ bool ToUtf8(const CFStringRef str16, std::string* str8) {
|
||||
size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
|
||||
kCFStringEncodingUTF8)
|
||||
+ 1;
|
||||
scoped_array<char> buffer(new char[maxlen]);
|
||||
scoped_ptr<char[]> buffer(new char[maxlen]);
|
||||
if (!buffer || !CFStringGetCString(str16, buffer.get(), maxlen,
|
||||
kCFStringEncodingUTF8))
|
||||
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) {
|
||||
scoped_array<char> output(new char[digest->Size()]);
|
||||
scoped_ptr<char[]> output(new char[digest->Size()]);
|
||||
ComputeDigest(digest, input.data(), input.size(),
|
||||
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.
|
||||
// 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) {
|
||||
ComputeDigest(digest, key, key_len, new_key.get(), block_len);
|
||||
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);
|
||||
}
|
||||
// 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) {
|
||||
o_pad[i] = 0x5c ^ new_key[i];
|
||||
i_pad[i] = 0x36 ^ new_key[i];
|
||||
}
|
||||
// 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(input, in_len);
|
||||
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,
|
||||
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(),
|
||||
input.data(), input.size(), 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.
|
||||
// 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 + kNATEncodedIPv6AddressSize,
|
||||
remote_addr);
|
||||
|
@ -154,7 +154,7 @@ class NATSocket : public AsyncSocket, public sigslot::has_slots<> {
|
||||
return socket_->SendTo(data, size, addr);
|
||||
}
|
||||
// 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 + kNATEncodedIPv6AddressSize,
|
||||
addr);
|
||||
|
@ -109,7 +109,7 @@ bool HasIPv6Enabled() {
|
||||
return false;
|
||||
}
|
||||
DWORD protbuff_size = 4096;
|
||||
scoped_array<char> protocols;
|
||||
scoped_ptr<char[]> protocols;
|
||||
LPWSAPROTOCOL_INFOW protocol_infos = NULL;
|
||||
int requested_protocols[2] = {AF_INET6, 0};
|
||||
|
||||
|
@ -316,7 +316,7 @@ bool BasicNetworkManager::CreateNetworks(bool include_ignored,
|
||||
NetworkMap current_networks;
|
||||
// MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses.
|
||||
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 =
|
||||
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
|
||||
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));
|
||||
}
|
||||
|
||||
TEST_F(NetworkTest, TestCreateNetworks) {
|
||||
// Test is failing on Windows opt: b/11288214
|
||||
TEST_F(NetworkTest, DISABLED_TestCreateNetworks) {
|
||||
BasicNetworkManager manager;
|
||||
NetworkManager::NetworkList result = GetNetworks(manager, true);
|
||||
// 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;
|
||||
*sopt = TCP_NODELAY;
|
||||
break;
|
||||
case OPT_DSCP:
|
||||
LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
|
||||
return -1;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
|
@ -1,34 +1,102 @@
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// 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.
|
||||
//
|
||||
// Borrowed from chromium.
|
||||
// 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.
|
||||
|
||||
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
||||
// of the object pointed to, either on destruction of the scoped_ptr or via
|
||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
||||
// use shared_ptr or std::auto_ptr if your needs are more complex.
|
||||
// Scopers help you manage ownership of a pointer, helping you easily manage the
|
||||
// a pointer within a scope, and automatically destroying the pointer at the
|
||||
// end of a scope. There are two main classes you will use, which correspond
|
||||
// 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__
|
||||
#define TALK_BASE_SCOPED_PTR_H__
|
||||
|
||||
#include <cstddef> // for std::ptrdiff_t
|
||||
#include <stdlib.h> // for free() decl
|
||||
|
||||
#include <algorithm> // For std::swap().
|
||||
|
||||
#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
|
||||
namespace std { using ::ptrdiff_t; };
|
||||
@ -36,242 +104,495 @@ namespace std { using ::ptrdiff_t; };
|
||||
|
||||
namespace talk_base {
|
||||
|
||||
template <typename T>
|
||||
class scoped_ptr {
|
||||
private:
|
||||
|
||||
T* ptr;
|
||||
|
||||
scoped_ptr(scoped_ptr const &);
|
||||
scoped_ptr & operator=(scoped_ptr const &);
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_ptr(T* p = NULL): ptr(p) {}
|
||||
|
||||
~scoped_ptr() {
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
// Function object which deletes its parameter, which must be a pointer.
|
||||
// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
|
||||
// invokes 'delete'. The default deleter for scoped_ptr<T>.
|
||||
template <class T>
|
||||
struct DefaultDeleter {
|
||||
DefaultDeleter() {}
|
||||
template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
|
||||
// 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.
|
||||
//
|
||||
// Correct implementation should use SFINAE to disable this
|
||||
// constructor. However, since there are no other 1-argument constructors,
|
||||
// using a COMPILE_ASSERT() based on is_convertible<> and requiring
|
||||
// complete types is simpler and will cause compile failures for equivalent
|
||||
// misuses.
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 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)];
|
||||
// Specialization of DefaultDeleter for array types.
|
||||
template <class T>
|
||||
struct DefaultDeleter<T[]> {
|
||||
inline void operator()(T* ptr) const {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
delete[] ptr;
|
||||
}
|
||||
|
||||
void reset(T* p = NULL) {
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
private:
|
||||
// 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) {
|
||||
T* arr = ptr;
|
||||
ptr = p;
|
||||
// Delete last, in case arr destructor indirectly results in ~scoped_array
|
||||
delete [] arr;
|
||||
template <class T, int n>
|
||||
struct DefaultDeleter<T[n]> {
|
||||
// Never allow someone to declare something like scoped_ptr<int[10]>.
|
||||
COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
|
||||
};
|
||||
|
||||
// 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 {
|
||||
ASSERT(ptr != NULL);
|
||||
ASSERT(i >= 0);
|
||||
return ptr[i];
|
||||
void reset(T* p) {
|
||||
// This is a self-reset, which is no longer allowed: http://crbug.com/162971
|
||||
if (p != NULL && p == data_.ptr)
|
||||
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 {
|
||||
return ptr;
|
||||
}
|
||||
T* get() const { return data_.ptr; }
|
||||
|
||||
void swap(scoped_array & b) {
|
||||
T* tmp = b.ptr;
|
||||
b.ptr = ptr;
|
||||
ptr = tmp;
|
||||
D& get_deleter() { return data_; }
|
||||
const D& get_deleter() const { return data_; }
|
||||
|
||||
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* tmp = ptr;
|
||||
ptr = NULL;
|
||||
return tmp;
|
||||
T* old_ptr = data_.ptr;
|
||||
data_.ptr = NULL;
|
||||
return old_ptr;
|
||||
}
|
||||
|
||||
T** accept() {
|
||||
if (ptr) {
|
||||
delete [] ptr;
|
||||
ptr = NULL;
|
||||
}
|
||||
return &ptr;
|
||||
reset(NULL);
|
||||
return &(data_.ptr);
|
||||
}
|
||||
|
||||
// Allow scoped_array<T> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
// Borrowed from chromium's scoped_array implementation.
|
||||
typedef T* scoped_array::*Testable;
|
||||
operator Testable() const { return ptr ? &scoped_array::ptr : NULL; }
|
||||
T** use() {
|
||||
return &(data_.ptr);
|
||||
}
|
||||
|
||||
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
|
||||
void swap(scoped_array<T>& a, scoped_array<T>& b) {
|
||||
a.swap(b);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
|
||||
// second template argument, the function used to free the object.
|
||||
|
||||
template<typename T, void (*FF)(T*) = free> class scoped_ptr_malloc {
|
||||
private:
|
||||
|
||||
T* ptr;
|
||||
|
||||
scoped_ptr_malloc(scoped_ptr_malloc const &);
|
||||
scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
|
||||
// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
|
||||
// automatically deletes the pointer it holds (if any).
|
||||
// That is, scoped_ptr<T> owns the T object that it points to.
|
||||
// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
|
||||
// Also like T*, scoped_ptr<T> is thread-compatible, and once you
|
||||
// dereference it, you get the thread safety guarantees of T.
|
||||
//
|
||||
// The size of scoped_ptr is small. On most compilers, when using the
|
||||
// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
|
||||
// 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:
|
||||
|
||||
// The element and deleter types.
|
||||
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() {
|
||||
FF(ptr);
|
||||
// Constructor. Takes ownership of p.
|
||||
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) {
|
||||
if (ptr != p) {
|
||||
FF(ptr);
|
||||
ptr = p;
|
||||
}
|
||||
// Constructor. Move constructor for C++03 move emulation of this type.
|
||||
scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
|
||||
|
||||
// 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 {
|
||||
ASSERT(ptr != 0);
|
||||
return *ptr;
|
||||
}
|
||||
// Reset. Deletes the currently owned object, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
void reset(element_type* p = NULL) { impl_.reset(p); }
|
||||
|
||||
T* operator->() const {
|
||||
ASSERT(ptr != 0);
|
||||
return ptr;
|
||||
// Accessors to get the owned object.
|
||||
// operator* and operator-> will assert() if there is no current object.
|
||||
element_type& operator*() const {
|
||||
ASSERT(impl_.get() != NULL);
|
||||
return *impl_.get();
|
||||
}
|
||||
|
||||
T* get() const {
|
||||
return ptr;
|
||||
element_type* operator->() const {
|
||||
ASSERT(impl_.get() != NULL);
|
||||
return impl_.get();
|
||||
}
|
||||
element_type* get() const { return impl_.get(); }
|
||||
|
||||
void swap(scoped_ptr_malloc & b) {
|
||||
T* tmp = b.ptr;
|
||||
b.ptr = ptr;
|
||||
ptr = tmp;
|
||||
}
|
||||
// Access to the deleter.
|
||||
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||
|
||||
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
|
||||
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
// Borrowed from chromium's scoped_ptr_malloc implementation.
|
||||
typedef T* scoped_ptr_malloc::*Testable;
|
||||
operator Testable() const { return ptr ? &scoped_ptr_malloc::ptr : NULL; }
|
||||
//
|
||||
// Note that this trick is only safe when the == and != operators
|
||||
// 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
|
||||
void swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& b) {
|
||||
a.swap(b);
|
||||
template <class T, class D>
|
||||
class scoped_ptr<T[], D> {
|
||||
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
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
} // namespace talk_base
|
||||
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__
|
||||
|
@ -693,8 +693,8 @@ void SocketTest::TcpInternal(const IPAddress& loopback) {
|
||||
|
||||
// Create test data.
|
||||
const size_t kDataSize = 1024 * 1024;
|
||||
scoped_array<char> send_buffer(new char[kDataSize]);
|
||||
scoped_array<char> recv_buffer(new char[kDataSize]);
|
||||
scoped_ptr<char[]> send_buffer(new char[kDataSize]);
|
||||
scoped_ptr<char[]> recv_buffer(new char[kDataSize]);
|
||||
size_t send_pos = 0, recv_pos = 0;
|
||||
for (size_t i = 0; i < kDataSize; ++i) {
|
||||
send_buffer[i] = static_cast<char>(i % 256);
|
||||
@ -934,7 +934,7 @@ void SocketTest::UdpReadyToSend(const IPAddress& loopback) {
|
||||
scoped_ptr<TestClient> client(
|
||||
new TestClient(AsyncUDPSocket::Create(ss_, empty)));
|
||||
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.
|
||||
memset(test_packet.get(), 0, test_packet_size);
|
||||
// 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 {
|
||||
public:
|
||||
SSLIdentityTest() :
|
||||
identity1_(NULL), identity2_(NULL) {
|
||||
identity1_(), identity2_() {
|
||||
}
|
||||
|
||||
~SSLIdentityTest() {
|
||||
|
@ -166,7 +166,7 @@ StreamAdapterInterface::~StreamAdapterInterface() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
StreamTap::StreamTap(StreamInterface* stream, StreamInterface* tap)
|
||||
: StreamAdapterInterface(stream), tap_(NULL), tap_result_(SR_SUCCESS),
|
||||
: StreamAdapterInterface(stream), tap_(), tap_result_(SR_SUCCESS),
|
||||
tap_error_(0) {
|
||||
AttachTap(tap);
|
||||
}
|
||||
|
@ -691,7 +691,7 @@ class FifoBuffer : public StreamInterface {
|
||||
size_t offset, size_t* bytes_written);
|
||||
|
||||
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 data_length_; // amount of readable data in the buffer
|
||||
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.
|
||||
// Size can change between calls (unlikely), so a loop is done.
|
||||
DWORD return_length = 0;
|
||||
scoped_array<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> infos;
|
||||
scoped_ptr<SYSTEM_LOGICAL_PROCESSOR_INFORMATION[]> infos;
|
||||
while (!glpi(infos.get(), &return_length)) {
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
infos.reset(new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[
|
||||
@ -183,6 +183,8 @@ SystemInfo::SystemInfo()
|
||||
if (!sysctlbyname("machdep.cpu.stepping", &sysctl_value, &length, NULL, 0)) {
|
||||
cpu_stepping_ = static_cast<int>(sysctl_value);
|
||||
}
|
||||
#elif defined(__native_client__)
|
||||
// TODO(ryanpetrie): Implement this via PPAPI when it's available.
|
||||
#else // LINUX || ANDROID
|
||||
ProcCpuInfo proc_info;
|
||||
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);
|
||||
|
||||
// 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>(
|
||||
token_user_bytes.get());
|
||||
memset(token_user, 0, token_user_size);
|
||||
@ -137,7 +137,7 @@ bool Win32Filesystem::CreatePrivateFile(const Pathname &filename) {
|
||||
GetLengthSid(token_user->User.Sid);
|
||||
|
||||
// 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());
|
||||
memset(acl, 0, acl_size);
|
||||
if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) {
|
||||
@ -440,7 +440,7 @@ bool Win32Filesystem::GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
|
||||
Pathname Win32Filesystem::GetCurrentDirectory() {
|
||||
Pathname cwd;
|
||||
int path_len = 0;
|
||||
scoped_array<wchar_t> path;
|
||||
scoped_ptr<wchar_t[]> path;
|
||||
do {
|
||||
int needed = ::GetCurrentDirectory(path_len, path.get());
|
||||
if (needed == 0) {
|
||||
|
@ -160,7 +160,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
|
||||
ASSERT(full_key_name != NULL);
|
||||
|
||||
DWORD byte_count = 0;
|
||||
scoped_array<byte> buffer;
|
||||
scoped_ptr<byte[]> buffer;
|
||||
HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
|
||||
REG_BINARY, buffer.accept(), &byte_count);
|
||||
if (SUCCEEDED(hr)) {
|
||||
@ -179,7 +179,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
|
||||
ASSERT(full_key_name != NULL);
|
||||
|
||||
DWORD byte_count = 0;
|
||||
scoped_array<byte> buffer;
|
||||
scoped_ptr<byte[]> buffer;
|
||||
HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
|
||||
REG_BINARY, buffer.accept(), &byte_count);
|
||||
if (SUCCEEDED(hr)) {
|
||||
@ -206,7 +206,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
|
||||
ASSERT(full_key_name != 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());
|
||||
if (SUCCEEDED(hr)) {
|
||||
value->assign(buffer.get());
|
||||
|
@ -620,6 +620,9 @@ int Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) {
|
||||
*slevel = IPPROTO_TCP;
|
||||
*sopt = TCP_NODELAY;
|
||||
break;
|
||||
case OPT_DSCP:
|
||||
LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
|
||||
return -1;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
|
@ -396,7 +396,7 @@ CallClient::CallClient(buzz::XmppClient* xmpp_client,
|
||||
transport_protocol_(cricket::ICEPROTO_HYBRID),
|
||||
sdes_policy_(cricket::SEC_DISABLED),
|
||||
dtls_policy_(cricket::SEC_DISABLED),
|
||||
ssl_identity_(NULL),
|
||||
ssl_identity_(),
|
||||
show_roster_messages_(false) {
|
||||
xmpp_client_->SignalStateChange.connect(this, &CallClient::OnStateChange);
|
||||
my_status_.set_caps_node(caps_node);
|
||||
|
@ -38,10 +38,10 @@
|
||||
|
||||
ChatApp::ChatApp(buzz::XmppClient* xmpp_client, talk_base::Thread* main_thread)
|
||||
: xmpp_client_(xmpp_client),
|
||||
presence_out_task_(NULL),
|
||||
presence_receive_task_(NULL),
|
||||
message_send_task_(NULL),
|
||||
message_received_task_(NULL),
|
||||
presence_out_task_(),
|
||||
presence_receive_task_(),
|
||||
message_send_task_(),
|
||||
message_received_task_(),
|
||||
console_task_(new buzz::ConsoleTask(main_thread)),
|
||||
ui_state_(STATE_BASE) {
|
||||
xmpp_client_->SignalStateChange.connect(this, &ChatApp::OnStateChange);
|
||||
|
@ -110,7 +110,7 @@ class GtkMainWnd : public MainWindow {
|
||||
}
|
||||
|
||||
protected:
|
||||
talk_base::scoped_array<uint8> image_;
|
||||
talk_base::scoped_ptr<uint8[]> image_;
|
||||
int width_;
|
||||
int height_;
|
||||
GtkMainWnd* main_wnd_;
|
||||
|
@ -147,7 +147,7 @@ class MainWnd : public MainWindow {
|
||||
|
||||
HWND wnd_;
|
||||
BITMAPINFO bmi_;
|
||||
talk_base::scoped_array<uint8> image_;
|
||||
talk_base::scoped_ptr<uint8[]> image_;
|
||||
CRITICAL_SECTION buffer_lock_;
|
||||
talk_base::scoped_refptr<webrtc::VideoTrackInterface> rendered_track_;
|
||||
};
|
||||
|
@ -51,8 +51,8 @@ void CpuInfo::MaskCpuFlagsForTest(int enable_flags) {
|
||||
bool IsCoreIOrBetter() {
|
||||
#if !defined(DISABLE_YUV) && (defined(__i386__) || defined(__x86_64__) || \
|
||||
defined(_M_IX86) || defined(_M_X64))
|
||||
int cpu_info[4];
|
||||
libyuv::CpuId(cpu_info, 0); // Function 0: Vendor ID
|
||||
uint32 cpu_info[4];
|
||||
libyuv::CpuId(0, 0, &cpu_info[0]); // Function 0: Vendor ID
|
||||
if (cpu_info[1] == 0x756e6547 && cpu_info[3] == 0x49656e69 &&
|
||||
cpu_info[2] == 0x6c65746e) { // GenuineIntel
|
||||
// Detect CPU Family and Model
|
||||
@ -62,7 +62,7 @@ bool IsCoreIOrBetter() {
|
||||
// 13:12 - Processor Type
|
||||
// 19:16 - Extended Model
|
||||
// 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 model = ((cpu_info[0] >> 4) & 0x0f) | ((cpu_info[0] >> 12) & 0xf0);
|
||||
// CpuFamily | CpuModel | Name
|
||||
|
@ -101,7 +101,7 @@ class FakeVideoCapturer : public cricket::VideoCapturer {
|
||||
frame.time_stamp = initial_unix_timestamp_ + next_timestamp_;
|
||||
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();
|
||||
// Copy something non-zero into the buffer so Validate wont complain that
|
||||
// the frame is all duplicate.
|
||||
|
@ -162,29 +162,51 @@ struct AudioOptions {
|
||||
void SetAll(const AudioOptions& change) {
|
||||
echo_cancellation.SetFrom(change.echo_cancellation);
|
||||
auto_gain_control.SetFrom(change.auto_gain_control);
|
||||
rx_auto_gain_control.SetFrom(change.rx_auto_gain_control);
|
||||
noise_suppression.SetFrom(change.noise_suppression);
|
||||
highpass_filter.SetFrom(change.highpass_filter);
|
||||
stereo_swapping.SetFrom(change.stereo_swapping);
|
||||
typing_detection.SetFrom(change.typing_detection);
|
||||
aecm_generate_comfort_noise.SetFrom(change.aecm_generate_comfort_noise);
|
||||
conference_mode.SetFrom(change.conference_mode);
|
||||
adjust_agc_delta.SetFrom(change.adjust_agc_delta);
|
||||
experimental_agc.SetFrom(change.experimental_agc);
|
||||
experimental_aec.SetFrom(change.experimental_aec);
|
||||
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 {
|
||||
return echo_cancellation == o.echo_cancellation &&
|
||||
auto_gain_control == o.auto_gain_control &&
|
||||
rx_auto_gain_control == o.rx_auto_gain_control &&
|
||||
noise_suppression == o.noise_suppression &&
|
||||
highpass_filter == o.highpass_filter &&
|
||||
stereo_swapping == o.stereo_swapping &&
|
||||
typing_detection == o.typing_detection &&
|
||||
aecm_generate_comfort_noise == o.aecm_generate_comfort_noise &&
|
||||
conference_mode == o.conference_mode &&
|
||||
experimental_agc == o.experimental_agc &&
|
||||
experimental_aec == o.experimental_aec &&
|
||||
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 {
|
||||
@ -192,15 +214,27 @@ struct AudioOptions {
|
||||
ost << "AudioOptions {";
|
||||
ost << ToStringIfSet("aec", echo_cancellation);
|
||||
ost << ToStringIfSet("agc", auto_gain_control);
|
||||
ost << ToStringIfSet("rx_agc", rx_auto_gain_control);
|
||||
ost << ToStringIfSet("ns", noise_suppression);
|
||||
ost << ToStringIfSet("hf", highpass_filter);
|
||||
ost << ToStringIfSet("swap", stereo_swapping);
|
||||
ost << ToStringIfSet("typing", typing_detection);
|
||||
ost << ToStringIfSet("comfort_noise", aecm_generate_comfort_noise);
|
||||
ost << ToStringIfSet("conference", conference_mode);
|
||||
ost << ToStringIfSet("agc_delta", adjust_agc_delta);
|
||||
ost << ToStringIfSet("experimental_agc", experimental_agc);
|
||||
ost << ToStringIfSet("experimental_aec", experimental_aec);
|
||||
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 << "}";
|
||||
return ost.str();
|
||||
}
|
||||
@ -210,6 +244,8 @@ struct AudioOptions {
|
||||
Settable<bool> echo_cancellation;
|
||||
// Audio processing to adjust the sensitivity of the local mic dynamically.
|
||||
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.
|
||||
Settable<bool> noise_suppression;
|
||||
// Audio processing to remove background noise of lower frequencies.
|
||||
@ -218,11 +254,21 @@ struct AudioOptions {
|
||||
Settable<bool> stereo_swapping;
|
||||
// Audio processing to detect typing.
|
||||
Settable<bool> typing_detection;
|
||||
Settable<bool> aecm_generate_comfort_noise;
|
||||
Settable<bool> conference_mode;
|
||||
Settable<int> adjust_agc_delta;
|
||||
Settable<bool> experimental_agc;
|
||||
Settable<bool> experimental_aec;
|
||||
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.
|
||||
@ -244,12 +290,13 @@ struct VideoOptions {
|
||||
video_adapt_third.SetFrom(change.video_adapt_third);
|
||||
video_noise_reduction.SetFrom(change.video_noise_reduction);
|
||||
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_high_bitrate.SetFrom(change.video_high_bitrate);
|
||||
video_watermark.SetFrom(change.video_watermark);
|
||||
video_temporal_layer_screencast.SetFrom(
|
||||
change.video_temporal_layer_screencast);
|
||||
video_temporal_layer_realtime.SetFrom(
|
||||
change.video_temporal_layer_realtime);
|
||||
video_leaky_bucket.SetFrom(change.video_leaky_bucket);
|
||||
cpu_overuse_detection.SetFrom(change.cpu_overuse_detection);
|
||||
conference_mode.SetFrom(change.conference_mode);
|
||||
@ -269,11 +316,11 @@ struct VideoOptions {
|
||||
video_adapt_third == o.video_adapt_third &&
|
||||
video_noise_reduction == o.video_noise_reduction &&
|
||||
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_high_bitrate == o.video_high_bitrate &&
|
||||
video_watermark == o.video_watermark &&
|
||||
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 &&
|
||||
cpu_overuse_detection == o.cpu_overuse_detection &&
|
||||
conference_mode == o.conference_mode &&
|
||||
@ -295,12 +342,13 @@ struct VideoOptions {
|
||||
ost << ToStringIfSet("video adapt third", video_adapt_third);
|
||||
ost << ToStringIfSet("noise reduction", video_noise_reduction);
|
||||
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("high bitrate", video_high_bitrate);
|
||||
ost << ToStringIfSet("watermark", video_watermark);
|
||||
ost << ToStringIfSet("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("cpu overuse detection", cpu_overuse_detection);
|
||||
ost << ToStringIfSet("conference mode", conference_mode);
|
||||
@ -326,8 +374,6 @@ struct VideoOptions {
|
||||
Settable<bool> video_noise_reduction;
|
||||
// Experimental: Enable multi layer?
|
||||
Settable<bool> video_three_layers;
|
||||
// Experimental: Enable camera list?
|
||||
Settable<bool> video_enable_camera_list;
|
||||
// Experimental: Enable one layer screencast?
|
||||
Settable<bool> video_one_layer_screencast;
|
||||
// Experimental: Enable WebRtc higher bitrate?
|
||||
@ -336,6 +382,8 @@ struct VideoOptions {
|
||||
Settable<bool> video_watermark;
|
||||
// Experimental: Enable WebRTC layered 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.
|
||||
Settable<bool> video_leaky_bucket;
|
||||
// Enable WebRTC Cpu Overuse Detection, which is a new version of the CPU
|
||||
@ -513,15 +561,68 @@ enum SendFlags {
|
||||
SEND_MICROPHONE
|
||||
};
|
||||
|
||||
struct VoiceSenderInfo {
|
||||
VoiceSenderInfo()
|
||||
// The stats information is structured as follows:
|
||||
// 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),
|
||||
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_lost(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),
|
||||
rtt_ms(0),
|
||||
jitter_ms(0),
|
||||
audio_level(0),
|
||||
aec_quality_min(0.0),
|
||||
@ -533,13 +634,7 @@ struct VoiceSenderInfo {
|
||||
}
|
||||
|
||||
uint32 ssrc;
|
||||
std::string codec_name;
|
||||
int64 bytes_sent;
|
||||
int packets_sent;
|
||||
int packets_lost;
|
||||
float fraction_lost;
|
||||
int ext_seqnum;
|
||||
int rtt_ms;
|
||||
int jitter_ms;
|
||||
int audio_level;
|
||||
float aec_quality_min;
|
||||
@ -550,13 +645,9 @@ struct VoiceSenderInfo {
|
||||
bool typing_noise_detected;
|
||||
};
|
||||
|
||||
struct VoiceReceiverInfo {
|
||||
struct VoiceReceiverInfo : public MediaReceiverInfo {
|
||||
VoiceReceiverInfo()
|
||||
: ssrc(0),
|
||||
bytes_rcvd(0),
|
||||
packets_rcvd(0),
|
||||
packets_lost(0),
|
||||
fraction_lost(0.0),
|
||||
ext_seqnum(0),
|
||||
jitter_ms(0),
|
||||
jitter_buffer_ms(0),
|
||||
@ -567,10 +658,6 @@ struct VoiceReceiverInfo {
|
||||
}
|
||||
|
||||
uint32 ssrc;
|
||||
int64 bytes_rcvd;
|
||||
int packets_rcvd;
|
||||
int packets_lost;
|
||||
float fraction_lost;
|
||||
int ext_seqnum;
|
||||
int jitter_ms;
|
||||
int jitter_buffer_ms;
|
||||
@ -581,16 +668,11 @@ struct VoiceReceiverInfo {
|
||||
float expand_rate;
|
||||
};
|
||||
|
||||
struct VideoSenderInfo {
|
||||
struct VideoSenderInfo : public MediaSenderInfo {
|
||||
VideoSenderInfo()
|
||||
: bytes_sent(0),
|
||||
packets_sent(0),
|
||||
packets_cached(0),
|
||||
packets_lost(0),
|
||||
fraction_lost(0.0),
|
||||
: packets_cached(0),
|
||||
firs_rcvd(0),
|
||||
nacks_rcvd(0),
|
||||
rtt_ms(0),
|
||||
frame_width(0),
|
||||
frame_height(0),
|
||||
framerate_input(0),
|
||||
@ -602,15 +684,9 @@ struct VideoSenderInfo {
|
||||
|
||||
std::vector<uint32> ssrcs;
|
||||
std::vector<SsrcGroup> ssrc_groups;
|
||||
std::string codec_name;
|
||||
int64 bytes_sent;
|
||||
int packets_sent;
|
||||
int packets_cached;
|
||||
int packets_lost;
|
||||
float fraction_lost;
|
||||
int firs_rcvd;
|
||||
int nacks_rcvd;
|
||||
int rtt_ms;
|
||||
int frame_width;
|
||||
int frame_height;
|
||||
int framerate_input;
|
||||
@ -620,13 +696,9 @@ struct VideoSenderInfo {
|
||||
int adapt_reason;
|
||||
};
|
||||
|
||||
struct VideoReceiverInfo {
|
||||
struct VideoReceiverInfo : public MediaReceiverInfo {
|
||||
VideoReceiverInfo()
|
||||
: bytes_rcvd(0),
|
||||
packets_rcvd(0),
|
||||
packets_lost(0),
|
||||
packets_concealed(0),
|
||||
fraction_lost(0.0),
|
||||
: packets_concealed(0),
|
||||
firs_sent(0),
|
||||
nacks_sent(0),
|
||||
frame_width(0),
|
||||
@ -635,17 +707,19 @@ struct VideoReceiverInfo {
|
||||
framerate_decoded(0),
|
||||
framerate_output(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<SsrcGroup> ssrc_groups;
|
||||
int64 bytes_rcvd;
|
||||
// vector<int> layer_bytes_rcvd;
|
||||
int packets_rcvd;
|
||||
int packets_lost;
|
||||
int packets_concealed;
|
||||
float fraction_lost;
|
||||
int firs_sent;
|
||||
int nacks_sent;
|
||||
int frame_width;
|
||||
@ -657,31 +731,42 @@ struct VideoReceiverInfo {
|
||||
int framerate_render_input;
|
||||
// Framerate that the renderer reports.
|
||||
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()
|
||||
: ssrc(0),
|
||||
bytes_sent(0),
|
||||
packets_sent(0) {
|
||||
: ssrc(0) {
|
||||
}
|
||||
|
||||
uint32 ssrc;
|
||||
std::string codec_name;
|
||||
int64 bytes_sent;
|
||||
int packets_sent;
|
||||
};
|
||||
|
||||
struct DataReceiverInfo {
|
||||
struct DataReceiverInfo : public MediaReceiverInfo {
|
||||
DataReceiverInfo()
|
||||
: ssrc(0),
|
||||
bytes_rcvd(0),
|
||||
packets_rcvd(0) {
|
||||
: ssrc(0) {
|
||||
}
|
||||
|
||||
uint32 ssrc;
|
||||
int64 bytes_rcvd;
|
||||
int packets_rcvd;
|
||||
};
|
||||
|
||||
struct BandwidthEstimationInfo {
|
||||
|
@ -373,7 +373,7 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
|
||||
// TODO(fbarchard): Avoid scale and convert if muted.
|
||||
// Temporary buffer is scoped here so it will persist until i420_frame.Init()
|
||||
// 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
|
||||
// a problem on OSX. OSX always converts webcams to YUY2 or UYVY.
|
||||
bool can_scale =
|
||||
|
@ -153,12 +153,15 @@ void ComputeScale(int frame_width, int frame_height, int fps,
|
||||
|
||||
// Compute size to crop video frame to.
|
||||
// If cropped_format_* is 0, return the frame_* size as is.
|
||||
void ComputeCrop(int cropped_format_width,
|
||||
int cropped_format_height,
|
||||
void ComputeCrop(int cropped_format_width, int cropped_format_height,
|
||||
int frame_width, int frame_height,
|
||||
int pixel_width, int pixel_height,
|
||||
int rotation,
|
||||
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_height >= 0);
|
||||
ASSERT(frame_width > 0);
|
||||
@ -182,39 +185,26 @@ void ComputeCrop(int cropped_format_width,
|
||||
static_cast<float>(frame_height * pixel_height);
|
||||
float crop_aspect = static_cast<float>(cropped_format_width) /
|
||||
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
|
||||
// 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.
|
||||
// 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
|
||||
if (frame_aspect > crop_aspect &&
|
||||
frame_aspect < crop_aspect * kAspectThresh) {
|
||||
// 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
|
||||
// that avoids rounding errors. lmi and webrtc have odd width limitations.
|
||||
new_frame_width = static_cast<int>((crop_aspect * frame_height *
|
||||
// that avoids rounding errors.
|
||||
frame_width = static_cast<int>((crop_aspect * frame_height *
|
||||
pixel_height) / pixel_width + 0.5f) & ~3;
|
||||
} else if (crop_aspect > frame_aspect &&
|
||||
crop_aspect < frame_aspect * kAspectThresh) {
|
||||
new_frame_height = static_cast<int>((frame_width * pixel_width) /
|
||||
} else if (frame_aspect < crop_aspect &&
|
||||
frame_aspect > crop_aspect / kAspectThresh) {
|
||||
frame_height = static_cast<int>((frame_width * pixel_width) /
|
||||
(crop_aspect * pixel_height) + 0.5f) & ~1;
|
||||
}
|
||||
|
||||
*cropped_width = new_frame_width;
|
||||
*cropped_height = new_frame_height;
|
||||
if (rotation == 90 || rotation == 270) {
|
||||
*cropped_width = new_frame_height;
|
||||
*cropped_height = new_frame_width;
|
||||
}
|
||||
*cropped_width = frame_width;
|
||||
*cropped_height = frame_height;
|
||||
}
|
||||
|
||||
// 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(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.
|
||||
// This is used when adding multiple capturers
|
||||
ComputeCrop(0, 0, // Crop size 0x0
|
||||
|
@ -157,7 +157,7 @@ class VideoFrameTest : public testing::Test {
|
||||
prefix.c_str(), frame.GetWidth(), frame.GetHeight());
|
||||
size_t out_size = cricket::VideoFrame::SizeOf(frame.GetWidth(),
|
||||
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);
|
||||
return DumpSample(filename, out.get(), out_size);
|
||||
}
|
||||
@ -514,7 +514,7 @@ class VideoFrameTest : public testing::Test {
|
||||
T frame1, frame2;
|
||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||
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* u = y + kWidth * kHeight;
|
||||
uint8* v = u + (kWidth / 2) * kHeight;
|
||||
@ -535,7 +535,7 @@ class VideoFrameTest : public testing::Test {
|
||||
T frame1, frame2;
|
||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||
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);
|
||||
EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.GetYPlane(), frame1.GetYPitch(),
|
||||
frame1.GetUPlane(), frame1.GetUPitch(),
|
||||
@ -552,7 +552,7 @@ class VideoFrameTest : public testing::Test {
|
||||
T frame1, frame2;
|
||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||
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;
|
||||
EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.GetYPlane(), frame1.GetYPitch(),
|
||||
frame1.GetUPlane(), frame1.GetUPitch(),
|
||||
@ -718,7 +718,7 @@ class VideoFrameTest : public testing::Test {
|
||||
void ConstructRGB565() {
|
||||
T frame1, frame2;
|
||||
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);
|
||||
T frame;
|
||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||
@ -734,7 +734,7 @@ class VideoFrameTest : public testing::Test {
|
||||
void ConstructARGB1555() {
|
||||
T frame1, frame2;
|
||||
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);
|
||||
T frame;
|
||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||
@ -750,7 +750,7 @@ class VideoFrameTest : public testing::Test {
|
||||
void ConstructARGB4444() {
|
||||
T frame1, frame2;
|
||||
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);
|
||||
T frame;
|
||||
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
|
||||
@ -769,7 +769,7 @@ class VideoFrameTest : public testing::Test {
|
||||
#define TEST_BYR(NAME, BAYER) \
|
||||
void NAME() { \
|
||||
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]); \
|
||||
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment); \
|
||||
T frame1, frame2; \
|
||||
@ -994,7 +994,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
}
|
||||
// Convert back to ARGB.
|
||||
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);
|
||||
|
||||
EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB,
|
||||
@ -1031,7 +1031,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
}
|
||||
// Convert back to ARGB
|
||||
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);
|
||||
|
||||
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.
|
||||
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)]);
|
||||
uint8* data_ptr = page_buffer.get();
|
||||
if (!data_ptr) {
|
||||
@ -1427,7 +1427,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
|
||||
int astride = kWidth * bpp + rowpad;
|
||||
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);
|
||||
uint8 *outtop = ALIGNP(outbuf.get(), kAlignment);
|
||||
uint8 *out = outtop;
|
||||
@ -1841,7 +1841,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
void ConvertToI422Buffer() {
|
||||
T frame1, frame2;
|
||||
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* u = y + kWidth * kHeight;
|
||||
uint8* v = u + (kWidth / 2) * kHeight;
|
||||
@ -1865,7 +1865,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
#define TEST_TOBYR(NAME, BAYER) \
|
||||
void NAME() { \
|
||||
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]); \
|
||||
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment); \
|
||||
T frame; \
|
||||
@ -1894,7 +1894,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
} \
|
||||
void NAME##Unaligned() { \
|
||||
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]); \
|
||||
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment) + 1; \
|
||||
T frame; \
|
||||
@ -1931,7 +1931,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
#define TEST_BYRTORGB(NAME, BAYER) \
|
||||
void NAME() { \
|
||||
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]); \
|
||||
uint8 *bayer1 = ALIGNP(bayerbuf.get(), kAlignment); \
|
||||
for (int i = 0; i < kWidth * kHeight; ++i) { \
|
||||
@ -1947,7 +1947,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
kWidth * 4, \
|
||||
kWidth, kHeight); \
|
||||
} \
|
||||
talk_base::scoped_array<uint8> bayer2buf(new uint8[ \
|
||||
talk_base::scoped_ptr<uint8[]> bayer2buf(new uint8[ \
|
||||
bayer_size + kAlignment]); \
|
||||
uint8 *bayer2 = ALIGNP(bayer2buf.get(), kAlignment); \
|
||||
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,
|
||||
&frame));
|
||||
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) {
|
||||
EXPECT_EQ(out_size, frame.CopyToBuffer(out.get(), out_size));
|
||||
}
|
||||
@ -2056,7 +2056,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
|
||||
|
||||
void CopyToBuffer1Pixel() {
|
||||
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
|
||||
uint8 pixel[3] = { 1, 2, 3 };
|
||||
T frame;
|
||||
|
@ -57,7 +57,7 @@ class CarbonVideoRenderer : public VideoRenderer {
|
||||
static OSStatus DrawEventHandler(EventHandlerCallRef handler,
|
||||
EventRef event,
|
||||
void* data);
|
||||
talk_base::scoped_array<uint8> image_;
|
||||
talk_base::scoped_ptr<uint8[]> image_;
|
||||
talk_base::CriticalSection image_crit_;
|
||||
int image_width_;
|
||||
int image_height_;
|
||||
|
@ -98,7 +98,7 @@ class GdiVideoRenderer::VideoWindow : public talk_base::Win32Window {
|
||||
void OnRenderFrame(const VideoFrame* frame);
|
||||
|
||||
BITMAPINFO bmi_;
|
||||
talk_base::scoped_array<uint8> image_;
|
||||
talk_base::scoped_ptr<uint8[]> image_;
|
||||
talk_base::scoped_ptr<WindowThread> window_thread_;
|
||||
// The initial position of the window.
|
||||
int initial_x_;
|
||||
|
@ -56,7 +56,7 @@ class GtkVideoRenderer : public VideoRenderer {
|
||||
// Check if the window has been closed.
|
||||
bool IsClosed() const;
|
||||
|
||||
talk_base::scoped_array<uint8> image_;
|
||||
talk_base::scoped_ptr<uint8[]> image_;
|
||||
GtkWidget* window_;
|
||||
GtkWidget* draw_area_;
|
||||
// The initial position of the window.
|
||||
|
@ -120,7 +120,7 @@ static bool GetAudioDeviceIDs(bool input,
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
|
||||
|
@ -56,7 +56,7 @@ struct socket;
|
||||
namespace cricket {
|
||||
// The highest stream ID (Sid) that SCTP allows, and the number of streams we
|
||||
// tell SCTP we're going to use.
|
||||
const uint32 kMaxSctpSid = USHRT_MAX;
|
||||
const uint32 kMaxSctpSid = 1023;
|
||||
|
||||
// A DataEngine that interacts with usrsctp.
|
||||
//
|
||||
|
@ -35,7 +35,7 @@
|
||||
namespace cricket {
|
||||
|
||||
// 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;
|
||||
|
||||
@ -73,16 +73,17 @@ bool ParseDataChannelOpenMessage(
|
||||
LOG(LS_WARNING) << "Could not read OPEN message channel type.";
|
||||
return false;
|
||||
}
|
||||
uint16 reliability_param;
|
||||
if (!buffer.ReadUInt16(&reliability_param)) {
|
||||
LOG(LS_WARNING) << "Could not read OPEN message reliabilility param.";
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 priority;
|
||||
if (!buffer.ReadUInt16(&priority)) {
|
||||
LOG(LS_WARNING) << "Could not read OPEN message reliabilility prioirty.";
|
||||
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;
|
||||
if (!buffer.ReadUInt16(&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_UNORDERED_PARTIAL_RTXS:
|
||||
config->maxRetransmits = reliability_param;
|
||||
|
||||
break;
|
||||
case DCOMCT_ORDERED_PARTIAL_TIME:
|
||||
case DCOMCT_UNORDERED_PARTIAL_TIME:
|
||||
config->maxRetransmitTime = reliability_param;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -130,11 +132,9 @@ bool WriteDataChannelOpenMessage(
|
||||
const webrtc::DataChannelInit& config,
|
||||
talk_base::Buffer* payload) {
|
||||
// Format defined at
|
||||
// http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
|
||||
// TODO(pthatcher)
|
||||
|
||||
// http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1
|
||||
uint8 channel_type = 0;
|
||||
uint16 reliability_param = 0;
|
||||
uint32 reliability_param = 0;
|
||||
uint16 priority = 0;
|
||||
if (config.ordered) {
|
||||
if (config.maxRetransmits > -1) {
|
||||
@ -163,8 +163,8 @@ bool WriteDataChannelOpenMessage(
|
||||
talk_base::ByteBuffer::ORDER_NETWORK);
|
||||
buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE);
|
||||
buffer.WriteUInt8(channel_type);
|
||||
buffer.WriteUInt16(reliability_param);
|
||||
buffer.WriteUInt16(priority);
|
||||
buffer.WriteUInt32(reliability_param);
|
||||
buffer.WriteUInt16(static_cast<uint16>(label.length()));
|
||||
buffer.WriteUInt16(static_cast<uint16>(config.protocol.length()));
|
||||
buffer.WriteString(label);
|
||||
|
@ -37,7 +37,7 @@ class SctpUtilsTest : public testing::Test {
|
||||
const webrtc::DataChannelInit& config) {
|
||||
uint8 message_type;
|
||||
uint8 channel_type;
|
||||
uint16 reliability;
|
||||
uint32 reliability;
|
||||
uint16 priority;
|
||||
uint16 label_length;
|
||||
uint16 protocol_length;
|
||||
@ -57,15 +57,15 @@ class SctpUtilsTest : public testing::Test {
|
||||
channel_type);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(buffer.ReadUInt16(&reliability));
|
||||
ASSERT_TRUE(buffer.ReadUInt16(&priority));
|
||||
|
||||
ASSERT_TRUE(buffer.ReadUInt32(&reliability));
|
||||
if (config.maxRetransmits > -1 || config.maxRetransmitTime > -1) {
|
||||
EXPECT_EQ(config.maxRetransmits > -1 ?
|
||||
config.maxRetransmits : config.maxRetransmitTime,
|
||||
reliability);
|
||||
static_cast<int>(reliability));
|
||||
}
|
||||
|
||||
ASSERT_TRUE(buffer.ReadUInt16(&priority));
|
||||
|
||||
ASSERT_TRUE(buffer.ReadUInt16(&label_length));
|
||||
ASSERT_TRUE(buffer.ReadUInt16(&protocol_length));
|
||||
EXPECT_EQ(label.size(), label_length);
|
||||
@ -86,13 +86,14 @@ TEST_F(SctpUtilsTest, WriteParseMessageWithOrderedReliable) {
|
||||
config.protocol = "y";
|
||||
|
||||
talk_base::Buffer packet;
|
||||
ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||
ASSERT_TRUE(
|
||||
cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||
|
||||
VerifyOpenMessageFormat(packet, input_label, config);
|
||||
|
||||
std::string output_label;
|
||||
webrtc::DataChannelInit output_config;
|
||||
ASSERT(cricket::ParseDataChannelOpenMessage(
|
||||
ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
|
||||
packet, &output_label, &output_config));
|
||||
|
||||
EXPECT_EQ(input_label, output_label);
|
||||
@ -110,19 +111,21 @@ TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmitTime) {
|
||||
config.protocol = "y";
|
||||
|
||||
talk_base::Buffer packet;
|
||||
ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||
ASSERT_TRUE(
|
||||
cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||
|
||||
VerifyOpenMessageFormat(packet, input_label, config);
|
||||
|
||||
std::string output_label;
|
||||
webrtc::DataChannelInit output_config;
|
||||
ASSERT(cricket::ParseDataChannelOpenMessage(
|
||||
ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
|
||||
packet, &output_label, &output_config));
|
||||
|
||||
EXPECT_EQ(input_label, output_label);
|
||||
EXPECT_EQ(config.protocol, output_config.protocol);
|
||||
EXPECT_EQ(config.ordered, output_config.ordered);
|
||||
EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime);
|
||||
EXPECT_EQ(-1, output_config.maxRetransmits);
|
||||
}
|
||||
|
||||
TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) {
|
||||
@ -132,17 +135,19 @@ TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) {
|
||||
config.protocol = "y";
|
||||
|
||||
talk_base::Buffer packet;
|
||||
ASSERT(cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||
ASSERT_TRUE(
|
||||
cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
|
||||
|
||||
VerifyOpenMessageFormat(packet, input_label, config);
|
||||
|
||||
std::string output_label;
|
||||
webrtc::DataChannelInit output_config;
|
||||
ASSERT(cricket::ParseDataChannelOpenMessage(
|
||||
ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
|
||||
packet, &output_label, &output_config));
|
||||
|
||||
EXPECT_EQ(input_label, output_label);
|
||||
EXPECT_EQ(config.protocol, output_config.protocol);
|
||||
EXPECT_EQ(config.ordered, output_config.ordered);
|
||||
EXPECT_EQ(config.maxRetransmits, output_config.maxRetransmits);
|
||||
EXPECT_EQ(-1, output_config.maxRetransmitTime);
|
||||
}
|
||||
|
@ -1046,7 +1046,14 @@ class FakeWebRtcVideoEngine
|
||||
return 0;
|
||||
}
|
||||
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_FUNC(RegisterExternalSendCodec,
|
||||
(const int channel, const unsigned char pl_type, webrtc::VideoEncoder*,
|
||||
|
@ -87,6 +87,8 @@ class FakeWebRtcVoiceEngine
|
||||
fec(false),
|
||||
nack(false),
|
||||
media_processor_registered(false),
|
||||
rx_agc_enabled(false),
|
||||
rx_agc_mode(webrtc::kAgcDefault),
|
||||
cn8_type(13),
|
||||
cn16_type(105),
|
||||
dtmf_type(106),
|
||||
@ -95,6 +97,7 @@ class FakeWebRtcVoiceEngine
|
||||
send_ssrc(0),
|
||||
level_header_ext_(-1) {
|
||||
memset(&send_codec, 0, sizeof(send_codec));
|
||||
memset(&rx_agc_config, 0, sizeof(rx_agc_config));
|
||||
}
|
||||
bool external_transport;
|
||||
bool send;
|
||||
@ -107,6 +110,9 @@ class FakeWebRtcVoiceEngine
|
||||
bool fec;
|
||||
bool nack;
|
||||
bool media_processor_registered;
|
||||
bool rx_agc_enabled;
|
||||
webrtc::AgcModes rx_agc_mode;
|
||||
webrtc::AgcConfig rx_agc_config;
|
||||
int cn8_type;
|
||||
int cn16_type;
|
||||
int dtmf_type;
|
||||
@ -144,6 +150,8 @@ class FakeWebRtcVoiceEngine
|
||||
send_fail_channel_(-1),
|
||||
fail_start_recording_microphone_(false),
|
||||
recording_microphone_(false),
|
||||
recording_sample_rate_(-1),
|
||||
playout_sample_rate_(-1),
|
||||
media_processor_(NULL) {
|
||||
memset(&agc_config_, 0, sizeof(agc_config_));
|
||||
}
|
||||
@ -584,10 +592,22 @@ class FakeWebRtcVoiceEngine
|
||||
WEBRTC_STUB(AudioDeviceControl, (unsigned int, unsigned int, unsigned int));
|
||||
WEBRTC_STUB(SetLoudspeakerStatus, (bool enable));
|
||||
WEBRTC_STUB(GetLoudspeakerStatus, (bool& enabled));
|
||||
WEBRTC_STUB(SetRecordingSampleRate, (unsigned int samples_per_sec));
|
||||
WEBRTC_STUB_CONST(RecordingSampleRate, (unsigned int* samples_per_sec));
|
||||
WEBRTC_STUB(SetPlayoutSampleRate, (unsigned int samples_per_sec));
|
||||
WEBRTC_STUB_CONST(PlayoutSampleRate, (unsigned int* samples_per_sec));
|
||||
WEBRTC_FUNC(SetRecordingSampleRate, (unsigned int samples_per_sec)) {
|
||||
recording_sample_rate_ = samples_per_sec;
|
||||
return 0;
|
||||
}
|
||||
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));
|
||||
virtual bool BuiltInAECIsEnabled() const { return true; }
|
||||
|
||||
@ -841,12 +861,27 @@ class FakeWebRtcVoiceEngine
|
||||
WEBRTC_STUB(SetRxNsStatus, (int channel, bool enable, webrtc::NsModes mode));
|
||||
WEBRTC_STUB(GetRxNsStatus, (int channel, bool& enabled,
|
||||
webrtc::NsModes& mode));
|
||||
WEBRTC_STUB(SetRxAgcStatus, (int channel, bool enable,
|
||||
webrtc::AgcModes mode));
|
||||
WEBRTC_STUB(GetRxAgcStatus, (int channel, bool& enabled,
|
||||
webrtc::AgcModes& mode));
|
||||
WEBRTC_STUB(SetRxAgcConfig, (int channel, webrtc::AgcConfig config));
|
||||
WEBRTC_STUB(GetRxAgcConfig, (int channel, webrtc::AgcConfig& config));
|
||||
WEBRTC_FUNC(SetRxAgcStatus, (int channel, bool enable,
|
||||
webrtc::AgcModes mode)) {
|
||||
channels_[channel]->rx_agc_enabled = enable;
|
||||
channels_[channel]->rx_agc_mode = mode;
|
||||
return 0;
|
||||
}
|
||||
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(DeRegisterRxVadObserver, (int channel));
|
||||
@ -996,6 +1031,8 @@ class FakeWebRtcVoiceEngine
|
||||
int send_fail_channel_;
|
||||
bool fail_start_recording_microphone_;
|
||||
bool recording_microphone_;
|
||||
int recording_sample_rate_;
|
||||
int playout_sample_rate_;
|
||||
DtmfInfo dtmf_info_;
|
||||
webrtc::VoEMediaProcess* media_processor_;
|
||||
};
|
||||
|
@ -309,6 +309,13 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
|
||||
: video_channel_(video_channel),
|
||||
framerate_(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) {
|
||||
}
|
||||
|
||||
@ -323,23 +330,42 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
|
||||
framerate_ = framerate;
|
||||
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) {
|
||||
talk_base::CritScope cs(&crit_);
|
||||
ASSERT(video_channel_ == videoChannel);
|
||||
++firs_requested_;
|
||||
}
|
||||
|
||||
int framerate() const {
|
||||
// Populate |rinfo| based on previously-set data in |*this|.
|
||||
void ExportTo(VideoReceiverInfo* rinfo) {
|
||||
talk_base::CritScope cs(&crit_);
|
||||
return framerate_;
|
||||
}
|
||||
int bitrate() const {
|
||||
talk_base::CritScope cs(&crit_);
|
||||
return bitrate_;
|
||||
}
|
||||
int firs_requested() const {
|
||||
talk_base::CritScope cs(&crit_);
|
||||
return firs_requested_;
|
||||
rinfo->firs_sent = firs_requested_;
|
||||
rinfo->framerate_rcvd = framerate_;
|
||||
rinfo->decode_ms = decode_ms_;
|
||||
rinfo->max_decode_ms = max_decode_ms_;
|
||||
rinfo->current_delay_ms = current_delay_ms_;
|
||||
rinfo->target_delay_ms = target_delay_ms_;
|
||||
rinfo->jitter_buffer_ms = jitter_buffer_ms_;
|
||||
rinfo->min_playout_delay_ms = min_playout_delay_ms_;
|
||||
rinfo->render_delay_ms = render_delay_ms_;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -347,6 +373,13 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
|
||||
int video_channel_;
|
||||
int framerate_;
|
||||
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_;
|
||||
};
|
||||
|
||||
@ -2303,14 +2336,13 @@ bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) {
|
||||
rinfo.packets_lost = -1;
|
||||
rinfo.packets_concealed = -1;
|
||||
rinfo.fraction_lost = -1; // from SentRTCP
|
||||
rinfo.firs_sent = channel->decoder_observer()->firs_requested();
|
||||
rinfo.nacks_sent = -1;
|
||||
rinfo.frame_width = channel->render_adapter()->width();
|
||||
rinfo.frame_height = channel->render_adapter()->height();
|
||||
rinfo.framerate_rcvd = channel->decoder_observer()->framerate();
|
||||
int fps = channel->render_adapter()->framerate();
|
||||
rinfo.framerate_decoded = fps;
|
||||
rinfo.framerate_output = fps;
|
||||
channel->decoder_observer()->ExportTo(&rinfo);
|
||||
|
||||
// Get sent RTCP statistics.
|
||||
uint16 s_fraction_lost;
|
||||
|
@ -118,7 +118,7 @@ class WebRtcVideoEngineTestFake : public testing::Test,
|
||||
}
|
||||
cricket::WebRtcVideoFrame frame;
|
||||
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,
|
||||
width, height, width, height,
|
||||
pixel.get(), size, 1, 1, 0, 0, 0)) {
|
||||
@ -138,7 +138,7 @@ class WebRtcVideoEngineTestFake : public testing::Test,
|
||||
}
|
||||
cricket::WebRtcVideoFrame frame;
|
||||
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,
|
||||
width, height, width, height,
|
||||
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());
|
||||
cricket::VideoOptions options;
|
||||
options.conference_mode.Set(true);
|
||||
|
@ -55,7 +55,7 @@ class FrameBuffer {
|
||||
const webrtc::VideoFrame* frame() const;
|
||||
|
||||
private:
|
||||
talk_base::scoped_array<char> data_;
|
||||
talk_base::scoped_ptr<char[]> data_;
|
||||
size_t length_;
|
||||
webrtc::VideoFrame video_frame_;
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ class WebRtcVideoFrameTest : public VideoFrameTest<cricket::WebRtcVideoFrame> {
|
||||
captured_frame.height = frame_height;
|
||||
captured_frame.data_size = (frame_width * frame_height) +
|
||||
((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]);
|
||||
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_render.h"
|
||||
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
|
||||
#include "webrtc/video_engine/new_include/frame_callback.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
|
@ -528,7 +528,7 @@ bool WebRtcVoiceEngine::InitInternal() {
|
||||
// Save the default AGC configuration settings. This must happen before
|
||||
// calling SetOptions or the default will be overwritten.
|
||||
if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) {
|
||||
LOG_RTCERR0(GetAGCConfig);
|
||||
LOG_RTCERR0(GetAgcConfig);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -686,6 +686,10 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
|
||||
webrtc::NsModes ns_mode = webrtc::kNsHighSuppression;
|
||||
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)
|
||||
// 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) {
|
||||
LOG_RTCERR2(SetEcStatus, echo_cancellation, ec_mode);
|
||||
return false;
|
||||
} else {
|
||||
LOG(LS_VERBOSE) << "Echo control set to " << echo_cancellation
|
||||
<< " with mode " << ec_mode;
|
||||
}
|
||||
#if !defined(ANDROID)
|
||||
// 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) {
|
||||
LOG_RTCERR2(SetAgcStatus, auto_gain_control, agc_mode);
|
||||
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) {
|
||||
LOG_RTCERR2(SetNsStatus, noise_suppression, ns_mode);
|
||||
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;
|
||||
}
|
||||
@ -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
|
||||
std::vector<std::string>::iterator recordEC =
|
||||
std::find(opts.begin(), opts.end(), "recordEC");
|
||||
@ -1587,6 +1655,56 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
|
||||
// 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: "
|
||||
<< options_.ToString();
|
||||
return true;
|
||||
|
@ -55,9 +55,10 @@ class FakeVoEWrapper : public cricket::VoEWrapper {
|
||||
}
|
||||
};
|
||||
|
||||
class NullVoETraceWrapper : public cricket::VoETraceWrapper {
|
||||
class FakeVoETraceWrapper : public cricket::VoETraceWrapper {
|
||||
public:
|
||||
virtual int SetTraceFilter(const unsigned int filter) {
|
||||
filter_ = filter;
|
||||
return 0;
|
||||
}
|
||||
virtual int SetTraceFile(const char* fileNameUTF8) {
|
||||
@ -66,6 +67,7 @@ class NullVoETraceWrapper : public cricket::VoETraceWrapper {
|
||||
virtual int SetTraceCallback(webrtc::TraceCallback* callback) {
|
||||
return 0;
|
||||
}
|
||||
unsigned int filter_;
|
||||
};
|
||||
|
||||
class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
@ -102,9 +104,10 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
WebRtcVoiceEngineTestFake()
|
||||
: voe_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
|
||||
voe_sc_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
|
||||
trace_wrapper_(new FakeVoETraceWrapper()),
|
||||
engine_(new FakeVoEWrapper(&voe_),
|
||||
new FakeVoEWrapper(&voe_sc_),
|
||||
new NullVoETraceWrapper()),
|
||||
trace_wrapper_),
|
||||
channel_(NULL), soundclip_(NULL) {
|
||||
options_conference_.conference_mode.Set(true);
|
||||
options_adjust_agc_.adjust_agc_delta.Set(-10);
|
||||
@ -277,6 +280,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
protected:
|
||||
cricket::FakeWebRtcVoiceEngine voe_;
|
||||
cricket::FakeWebRtcVoiceEngine voe_sc_;
|
||||
FakeVoETraceWrapper* trace_wrapper_;
|
||||
cricket::WebRtcVoiceEngine engine_;
|
||||
cricket::VoiceMediaChannel* channel_;
|
||||
cricket::SoundclipMedia* soundclip_;
|
||||
@ -1873,6 +1877,84 @@ TEST_F(WebRtcVoiceEngineTestFake, CodianSendAndPlayout) {
|
||||
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.
|
||||
// SSRC is set in SetupEngine by calling AddSendStream.
|
||||
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) {
|
||||
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;
|
||||
do {
|
||||
// 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.
|
||||
static const SocketAddress kPublicAddrs[2] =
|
||||
{ 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.
|
||||
static const SocketAddress kAlternateAddrs[2] =
|
||||
{ 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());
|
||||
}
|
||||
|
||||
// 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
|
||||
// to interesting behavior because the STUN server will only give out the
|
||||
// address of the outermost NAT.
|
||||
|
@ -215,7 +215,7 @@ class TestChannel : public sigslot::has_slots<> {
|
||||
public:
|
||||
TestChannel(Port* p1, Port* p2)
|
||||
: 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(
|
||||
this, &TestChannel::OnPortComplete);
|
||||
src_->SignalUnknownAddress.connect(this, &TestChannel::OnUnknownAddress);
|
||||
|
@ -539,7 +539,7 @@ IPseudoTcpNotify::WriteResult PseudoTcp::packet(uint32 seq, uint8 flags,
|
||||
|
||||
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(seq, buffer.get() + 4);
|
||||
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.
|
||||
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);
|
||||
if (size > mi_pos + kStunAttributeHeaderSize + kStunMessageIntegritySize) {
|
||||
// Stun message has other attributes after message integrity.
|
||||
|
@ -287,8 +287,13 @@ void UDPPort::SendStunBindingRequest() {
|
||||
if (server_addr_.IsUnresolved()) {
|
||||
ResolveStunAddress();
|
||||
} 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_));
|
||||
} 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_ext_addr)
|
||||
: server_(thread) {
|
||||
server_.AddInternalSocket(talk_base::AsyncUDPSocket::Create(
|
||||
thread->socketserver(), udp_int_addr), PROTO_UDP);
|
||||
AddInternalSocket(udp_int_addr, cricket::PROTO_UDP);
|
||||
server_.SetExternalSocketFactory(new talk_base::BasicPacketSocketFactory(),
|
||||
udp_ext_addr);
|
||||
server_.set_realm(kTestRealm);
|
||||
@ -62,6 +61,23 @@ class TestTurnServer : public TurnAuthInterface {
|
||||
|
||||
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:
|
||||
// For this test server, succeed if the password is the same as the username.
|
||||
// Obviously, do not use this in a production environment.
|
||||
|
@ -206,6 +206,14 @@ void TurnPort::PrepareAddress() {
|
||||
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()) {
|
||||
// We will set default TURN port, if no port is set in the address.
|
||||
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 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",
|
||||
cricket::TURN_SERVER_PORT);
|
||||
static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
|
||||
cricket::TURN_SERVER_PORT);
|
||||
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 kIceUfrag2[] = "TESTICEUFRAG0002";
|
||||
@ -71,6 +77,8 @@ static const cricket::ProtocolAddress kTurnUdpProtoAddr(
|
||||
kTurnUdpIntAddr, cricket::PROTO_UDP);
|
||||
static const cricket::ProtocolAddress kTurnTcpProtoAddr(
|
||||
kTurnTcpIntAddr, cricket::PROTO_TCP);
|
||||
static const cricket::ProtocolAddress kTurnUdpIPv6ProtoAddr(
|
||||
kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
|
||||
|
||||
class TurnPortTest : public testing::Test,
|
||||
public sigslot::has_slots<> {
|
||||
@ -130,9 +138,15 @@ class TurnPortTest : public testing::Test,
|
||||
void CreateTurnPort(const std::string& username,
|
||||
const std::string& password,
|
||||
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);
|
||||
turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
|
||||
kLocalAddr1.ipaddr(), 0, 0,
|
||||
local_address.ipaddr(), 0, 0,
|
||||
kIceUfrag1, kIcePwd1,
|
||||
server_address, credentials));
|
||||
turn_port_->SignalPortComplete.connect(this,
|
||||
@ -265,10 +279,7 @@ TEST_F(TurnPortTest, TestTurnAllocate) {
|
||||
}
|
||||
|
||||
TEST_F(TurnPortTest, TestTurnTcpAllocate) {
|
||||
talk_base::AsyncSocket* tcp_server_socket =
|
||||
CreateServerSocket(kTurnTcpIntAddr);
|
||||
turn_server_.server()->AddInternalServerSocket(
|
||||
tcp_server_socket, cricket::PROTO_TCP);
|
||||
turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
|
||||
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
||||
EXPECT_EQ(0, turn_port_->SetOption(talk_base::Socket::OPT_SNDBUF, 10*1024));
|
||||
turn_port_->PrepareAddress();
|
||||
@ -298,10 +309,7 @@ TEST_F(TurnPortTest, TestTurnConnection) {
|
||||
|
||||
// Test that we can establish a TCP connection with TURN server.
|
||||
TEST_F(TurnPortTest, TestTurnTcpConnection) {
|
||||
talk_base::AsyncSocket* tcp_server_socket =
|
||||
CreateServerSocket(kTurnTcpIntAddr);
|
||||
turn_server_.server()->AddInternalServerSocket(
|
||||
tcp_server_socket, cricket::PROTO_TCP);
|
||||
turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
|
||||
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
||||
TestTurnConnection();
|
||||
}
|
||||
@ -327,19 +335,44 @@ TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) {
|
||||
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) {
|
||||
// Create ports and prepare addresses.
|
||||
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
|
||||
TestTurnSendData();
|
||||
}
|
||||
|
||||
// Do a TURN allocation, establish a TCP connection, and send some data.
|
||||
TEST_F(TurnPortTest, TestTurnSendDataTurnTcpToUdp) {
|
||||
talk_base::AsyncSocket* tcp_server_socket =
|
||||
CreateServerSocket(kTurnTcpIntAddr);
|
||||
turn_server_.server()->AddInternalServerSocket(
|
||||
tcp_server_socket, cricket::PROTO_TCP);
|
||||
turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
|
||||
// Create ports and prepare addresses.
|
||||
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
|
||||
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),
|
||||
state_(kInit),
|
||||
flags_(flags),
|
||||
udp_socket_(NULL),
|
||||
udp_socket_(),
|
||||
phase_(0) {
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ class FakePortAllocatorSession : public PortAllocatorSession {
|
||||
factory_(factory),
|
||||
network_("network", "unittest",
|
||||
talk_base::IPAddress(INADDR_LOOPBACK), 8),
|
||||
port_(NULL), running_(false),
|
||||
port_(), running_(false),
|
||||
port_config_count_(0) {
|
||||
network_.AddIP(talk_base::IPAddress(INADDR_LOOPBACK));
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ using talk_base::SocketAddress;
|
||||
using talk_base::Thread;
|
||||
|
||||
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 kRemoteClientAddr("22.22.22.22", 0);
|
||||
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());
|
||||
}
|
||||
|
||||
// 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
|
||||
// relay servers, by never allowing an empty list.
|
||||
TEST(HttpPortAllocatorTest, TestHttpPortAllocatorHostLists) {
|
||||
|
@ -399,7 +399,6 @@ BaseChannel::BaseChannel(talk_base::Thread* thread,
|
||||
writable_(false),
|
||||
rtp_ready_to_send_(false),
|
||||
rtcp_ready_to_send_(false),
|
||||
optimistic_data_send_(false),
|
||||
was_ever_writable_(false),
|
||||
local_content_direction_(MD_INACTIVE),
|
||||
remote_content_direction_(MD_INACTIVE),
|
||||
@ -670,7 +669,7 @@ bool BaseChannel::SendPacket(bool rtcp, talk_base::Buffer* packet,
|
||||
// transport.
|
||||
TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
|
||||
transport_channel_ : rtcp_transport_channel_;
|
||||
if (!channel || (!optimistic_data_send_ && !channel->writable())) {
|
||||
if (!channel || !channel->writable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -97,10 +97,6 @@ class BaseChannel
|
||||
return rtcp_transport_channel_;
|
||||
}
|
||||
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.
|
||||
bool secure() const { return srtp_filter_.IsActive(); }
|
||||
@ -362,7 +358,6 @@ class BaseChannel
|
||||
bool writable_;
|
||||
bool rtp_ready_to_send_;
|
||||
bool rtcp_ready_to_send_;
|
||||
bool optimistic_data_send_;
|
||||
bool was_ever_writable_;
|
||||
MediaContentDirection local_content_direction_;
|
||||
MediaContentDirection remote_content_direction_;
|
||||
|
@ -496,11 +496,6 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
// 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.
|
||||
// kPcmuCodec is used as audio codec and kH264Codec is used as video codec.
|
||||
cricket::SessionDescription* CreateSessionDescriptionWithStream(uint32 ssrc) {
|
||||
@ -1394,19 +1389,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
EXPECT_TRUE(CheckNoRtp1());
|
||||
EXPECT_TRUE(CheckNoRtp2());
|
||||
|
||||
// Lose writability, with optimistic send
|
||||
SetOptimisticDataSend(true);
|
||||
// Lose writability, which should fail.
|
||||
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_TRUE(SendRtp2());
|
||||
EXPECT_TRUE(CheckRtp1());
|
||||
@ -1426,13 +1410,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
GetTransport1()->SetDestination(NULL);
|
||||
EXPECT_TRUE(media_channel1_->sending());
|
||||
|
||||
// Should fail regardless of optimistic send at this point.
|
||||
SetOptimisticDataSend(true);
|
||||
EXPECT_FALSE(SendRtp1());
|
||||
EXPECT_TRUE(SendRtp2());
|
||||
EXPECT_TRUE(CheckRtp1());
|
||||
EXPECT_TRUE(CheckNoRtp2());
|
||||
SetOptimisticDataSend(false);
|
||||
// Should fail also.
|
||||
EXPECT_FALSE(SendRtp1());
|
||||
EXPECT_TRUE(SendRtp2());
|
||||
EXPECT_TRUE(CheckRtp1());
|
||||
|
@ -46,7 +46,7 @@
|
||||
#ifdef HAVE_SCTP
|
||||
#include "talk/media/sctp/sctpdataengine.h"
|
||||
#else
|
||||
static const uint32 kMaxSctpSid = USHRT_MAX;
|
||||
static const uint32 kMaxSctpSid = 1023;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
@ -882,8 +882,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
|
||||
answer_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> answer(NULL);
|
||||
talk_base::scoped_ptr<SessionDescription> offer;
|
||||
talk_base::scoped_ptr<SessionDescription> answer;
|
||||
|
||||
offer_opts.rtcp_mux_enabled = true;
|
||||
answer_opts.rtcp_mux_enabled = true;
|
||||
|
@ -342,7 +342,7 @@ class AlsaInputStream :
|
||||
}
|
||||
|
||||
AlsaStream stream_;
|
||||
talk_base::scoped_array<char> buffer_;
|
||||
talk_base::scoped_ptr<char[]> buffer_;
|
||||
size_t buffer_size_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AlsaInputStream);
|
||||
|
@ -37,7 +37,7 @@ namespace buzz {
|
||||
|
||||
XmlBuilder::XmlBuilder() :
|
||||
pelCurrent_(NULL),
|
||||
pelRoot_(NULL),
|
||||
pelRoot_(),
|
||||
pvParents_(new std::vector<XmlElement *>()) {
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ public:
|
||||
|
||||
explicit Private(XmppClient* client) :
|
||||
client_(client),
|
||||
socket_(NULL),
|
||||
engine_(NULL),
|
||||
socket_(),
|
||||
engine_(),
|
||||
proxy_port_(0),
|
||||
pre_engine_error_(XmppEngine::ERROR_NONE),
|
||||
pre_engine_subcode_(0),
|
||||
|
@ -58,12 +58,12 @@ XmppEngineImpl::XmppEngineImpl()
|
||||
encrypted_(false),
|
||||
error_code_(ERROR_NONE),
|
||||
subcode_(0),
|
||||
stream_error_(NULL),
|
||||
stream_error_(),
|
||||
raised_reset_(false),
|
||||
output_handler_(NULL),
|
||||
session_handler_(NULL),
|
||||
iq_entries_(new IqEntryVector()),
|
||||
sasl_handler_(NULL),
|
||||
sasl_handler_(),
|
||||
output_(new std::stringstream()) {
|
||||
for (int i = 0; i < HL_COUNT; i+= 1) {
|
||||
stanza_handlers_[i].reset(new StanzaHandlerVector());
|
||||
|
@ -66,11 +66,11 @@ XmppLoginTask::XmppLoginTask(XmppEngineImpl * pctx) :
|
||||
pelStanza_(NULL),
|
||||
isStart_(false),
|
||||
iqId_(STR_EMPTY),
|
||||
pelFeatures_(NULL),
|
||||
pelFeatures_(),
|
||||
fullJid_(STR_EMPTY),
|
||||
streamId_(STR_EMPTY),
|
||||
pvecQueuedStanzas_(new std::vector<XmlElement *>()),
|
||||
sasl_mech_(NULL) {
|
||||
sasl_mech_() {
|
||||
}
|
||||
|
||||
XmppLoginTask::~XmppLoginTask() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user