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:
wu@webrtc.org 2013-10-25 21:18:33 +00:00
parent 728bc0fa4c
commit 97077a3ab2
95 changed files with 2086 additions and 640 deletions

2
DEPS
View File

@ -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",

View File

@ -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;
}

View File

@ -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_;

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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(

View File

@ -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;
}

View File

@ -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_;

View File

@ -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,

View File

@ -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

View File

@ -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_;

View File

@ -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

View File

@ -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[];

View File

@ -119,7 +119,6 @@ class FakeConstraints : public webrtc::MediaConstraintsInterface {
}
void SetAllowDtlsSctpDataChannels() {
SetMandatory(MediaConstraintsInterface::kEnableSctpDataChannels, true);
SetMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true);
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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.

View File

@ -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();

View File

@ -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);
};

View File

@ -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_;
};

View File

@ -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

View 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_

View File

@ -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)

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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
View 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_

View File

@ -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);

View File

@ -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);

View File

@ -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};

View File

@ -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 |

View File

@ -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.

View File

@ -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;

View File

@ -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__

View File

@ -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

View File

@ -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() {

View File

@ -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);
}

View File

@ -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

View File

@ -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
View 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_

View File

@ -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) {

View File

@ -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());

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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_;

View File

@ -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_;
};

View File

@ -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

View File

@ -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.

View File

@ -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 {

View File

@ -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 =

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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_;

View File

@ -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_;

View File

@ -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.

View File

@ -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,

View File

@ -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.
//

View File

@ -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);

View File

@ -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);
}

View File

@ -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*,

View File

@ -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_;
};

View File

@ -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;

View File

@ -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);

View File

@ -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_;
};

View File

@ -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();

View File

@ -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 {

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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();
}
}
}

View File

@ -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.

View File

@ -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);

View File

@ -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());
}

View File

@ -708,7 +708,7 @@ AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
config_(config),
state_(kInit),
flags_(flags),
udp_socket_(NULL),
udp_socket_(),
phase_(0) {
}

View File

@ -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));
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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_;

View File

@ -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());

View File

@ -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 {

View File

@ -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;

View File

@ -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);

View File

@ -37,7 +37,7 @@ namespace buzz {
XmlBuilder::XmlBuilder() :
pelCurrent_(NULL),
pelRoot_(NULL),
pelRoot_(),
pvParents_(new std::vector<XmlElement *>()) {
}

View File

@ -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),

View File

@ -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());

View File

@ -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() {