diff options
author | Torne (Richard Coles) <torne@google.com> | 2014-08-28 12:05:57 +0100 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2014-08-28 12:05:57 +0100 |
commit | 67bbc8e3efef31646fec91b0b422a78708a3f4aa (patch) | |
tree | 66c8a1f0d147229008546922886e68c884d6a833 | |
parent | 1ebe9245cb59449494489b9aed402f0d3f7f05b9 (diff) | |
parent | 9f1522d3d0637df349a76b8c81e6d075659fb84f (diff) | |
download | talk-67bbc8e3efef31646fec91b0b422a78708a3f4aa.tar.gz |
Merge from Chromium at DEPS revision 291560
This commit was generated by merge_to_master.py.
Change-Id: I64ade7f09d2b962ca9149b1fa2abfbc91bfe0832
28 files changed, 469 insertions, 396 deletions
diff --git a/app/webrtc/mediaconstraintsinterface.cc b/app/webrtc/mediaconstraintsinterface.cc index 74f6542..d59716e 100644 --- a/app/webrtc/mediaconstraintsinterface.cc +++ b/app/webrtc/mediaconstraintsinterface.cc @@ -93,8 +93,6 @@ const char MediaConstraintsInterface::kEnableDscp[] = "googDscp"; const char MediaConstraintsInterface::kEnableIPv6[] = "googIPv6"; const char MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate[] = "googSuspendBelowMinBitrate"; -const char MediaConstraintsInterface::kImprovedWifiBwe[] = - "googImprovedWifiBwe"; const char MediaConstraintsInterface::kNumUnsignalledRecvStreams[] = "googNumUnsignalledRecvStreams"; const char MediaConstraintsInterface::kScreencastMinBitrate[] = @@ -119,7 +117,6 @@ const char MediaConstraintsInterface::kHighBitrate[] = const char MediaConstraintsInterface::kVeryHighBitrate[] = "googVeryHighBitrate"; const char MediaConstraintsInterface::kPayloadPadding[] = "googPayloadPadding"; -const char MediaConstraintsInterface::kOpusFec[] = "googOpusFec"; // Set |value| to the value associated with the first appearance of |key|, or diff --git a/app/webrtc/mediaconstraintsinterface.h b/app/webrtc/mediaconstraintsinterface.h index b3efbb3..d74ffab 100644 --- a/app/webrtc/mediaconstraintsinterface.h +++ b/app/webrtc/mediaconstraintsinterface.h @@ -115,7 +115,6 @@ class MediaConstraintsInterface { // Temporary constraint to enable suspend below min bitrate feature. static const char kEnableVideoSuspendBelowMinBitrate[]; // googSuspendBelowMinBitrate - static const char kImprovedWifiBwe[]; // googImprovedWifiBwe static const char kNumUnsignalledRecvStreams[]; // googNumUnsignalledRecvStreams static const char kScreencastMinBitrate[]; // googScreencastMinBitrate @@ -133,8 +132,6 @@ class MediaConstraintsInterface { static const char kHighBitrate[]; // googHighBitrate static const char kVeryHighBitrate[]; // googVeryHighBitrate static const char kPayloadPadding[]; // googPayloadPadding - // kOpusFec controls whether we ask the other side to turn on FEC for Opus. - static const char kOpusFec[]; // googOpusFec // The prefix of internal-only constraints whose JS set values should be // stripped by Chrome before passed down to Libjingle. diff --git a/app/webrtc/peerconnection.cc b/app/webrtc/peerconnection.cc index 5b61048..201269a 100644 --- a/app/webrtc/peerconnection.cc +++ b/app/webrtc/peerconnection.cc @@ -85,11 +85,12 @@ struct SetSessionDescriptionMsg : public rtc::MessageData { }; struct GetStatsMsg : public rtc::MessageData { - explicit GetStatsMsg(webrtc::StatsObserver* observer) - : observer(observer) { + GetStatsMsg(webrtc::StatsObserver* observer, + webrtc::MediaStreamTrackInterface* track) + : observer(observer), track(track) { } - webrtc::StatsReports reports; rtc::scoped_refptr<webrtc::StatsObserver> observer; + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track; }; // |in_str| should be of format @@ -446,17 +447,15 @@ rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( bool PeerConnection::GetStats(StatsObserver* observer, MediaStreamTrackInterface* track, StatsOutputLevel level) { + ASSERT(signaling_thread()->IsCurrent()); if (!VERIFY(observer != NULL)) { LOG(LS_ERROR) << "GetStats - observer is NULL."; return false; } stats_->UpdateStats(level); - rtc::scoped_ptr<GetStatsMsg> msg(new GetStatsMsg(observer)); - if (!stats_->GetStats(track, &(msg->reports))) { - return false; - } - signaling_thread()->Post(this, MSG_GETSTATS, msg.release()); + signaling_thread()->Post(this, MSG_GETSTATS, + new GetStatsMsg(observer, track)); return true; } @@ -757,7 +756,9 @@ void PeerConnection::OnMessage(rtc::Message* msg) { } case MSG_GETSTATS: { GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata); - param->observer->OnComplete(param->reports); + StatsReports reports; + stats_->GetStats(param->track, &reports); + param->observer->OnComplete(reports); delete param; break; } diff --git a/app/webrtc/peerconnectionfactory.cc b/app/webrtc/peerconnectionfactory.cc index 81d864c..5dccba8 100644 --- a/app/webrtc/peerconnectionfactory.cc +++ b/app/webrtc/peerconnectionfactory.cc @@ -239,14 +239,14 @@ bool PeerConnectionFactory::Initialize_s() { new cricket::DummyDeviceManager()); // TODO: Need to make sure only one VoE is created inside // WebRtcMediaEngine. - cricket::WebRtcMediaEngine* webrtc_media_engine( - new cricket::WebRtcMediaEngine(default_adm_.get(), - NULL, // No secondary adm. - video_encoder_factory_.get(), - video_decoder_factory_.get())); + cricket::MediaEngineInterface* media_engine( + cricket::WebRtcMediaEngineFactory::Create(default_adm_.get(), + NULL, // No secondary adm. + video_encoder_factory_.get(), + video_decoder_factory_.get())); channel_manager_.reset(new cricket::ChannelManager( - webrtc_media_engine, device_manager, worker_thread_)); + media_engine, device_manager, worker_thread_)); channel_manager_->SetVideoRtxEnabled(true); if (!channel_manager_->Init()) { return false; diff --git a/app/webrtc/peerconnectioninterface.h b/app/webrtc/peerconnectioninterface.h index 59785e8..6ef4847 100644 --- a/app/webrtc/peerconnectioninterface.h +++ b/app/webrtc/peerconnectioninterface.h @@ -113,7 +113,18 @@ class StreamCollectionInterface : public rtc::RefCountInterface { class StatsObserver : public rtc::RefCountInterface { public: - virtual void OnComplete(const std::vector<StatsReport>& reports) = 0; + // TODO(tommi): Remove. + virtual void OnComplete(const std::vector<StatsReport>& reports) {} + + // TODO(tommi): Make pure virtual and remove implementation. + virtual void OnComplete(const StatsReports& reports) { + std::vector<StatsReportCopyable> report_copies; + for (size_t i = 0; i < reports.size(); ++i) + report_copies.push_back(StatsReportCopyable(*reports[i])); + std::vector<StatsReport>* r = + reinterpret_cast<std::vector<StatsReport>*>(&report_copies); + OnComplete(*r); + } protected: virtual ~StatsObserver() {} diff --git a/app/webrtc/statscollector.cc b/app/webrtc/statscollector.cc index 9e2d75b..5271827 100644 --- a/app/webrtc/statscollector.cc +++ b/app/webrtc/statscollector.cc @@ -234,7 +234,6 @@ void StatsReport::ReplaceValue(StatsReport::StatsValueName name, } namespace { -typedef std::map<std::string, StatsReport> StatsMap; double GetTimeNow() { return rtc::Timing::WallTimeNow() * rtc::kNumMillisecsPerSec; @@ -294,17 +293,16 @@ bool ExtractValueFromReport( return false; } -void AddTrackReport(StatsMap* reports, const std::string& track_id) { +void AddTrackReport(StatsSet* reports, const std::string& track_id) { // Adds an empty track report. - StatsReport report; - report.type = StatsReport::kStatsReportTypeTrack; - report.id = StatsId(StatsReport::kStatsReportTypeTrack, track_id); - report.AddValue(StatsReport::kStatsValueNameTrackId, track_id); - (*reports)[report.id] = report; + StatsReport* report = reports->ReplaceOrAddNew( + StatsId(StatsReport::kStatsReportTypeTrack, track_id)); + report->type = StatsReport::kStatsReportTypeTrack; + report->AddValue(StatsReport::kStatsValueNameTrackId, track_id); } template <class TrackVector> -void CreateTrackReports(const TrackVector& tracks, StatsMap* reports) { +void CreateTrackReports(const TrackVector& tracks, StatsSet* reports) { for (size_t j = 0; j < tracks.size(); ++j) { webrtc::MediaStreamTrackInterface* track = tracks[j]; AddTrackReport(reports, track->id()); @@ -469,7 +467,7 @@ void ExtractStats(const cricket::BandwidthEstimationInfo& info, double stats_gathering_started, PeerConnectionInterface::StatsOutputLevel level, StatsReport* report) { - report->id = StatsReport::kStatsReportVideoBweId; + ASSERT(report->id == StatsReport::kStatsReportVideoBweId); report->type = StatsReport::kStatsReportTypeBwe; // Clear out stats from previous GatherStats calls if any. @@ -583,9 +581,9 @@ void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track, // Create the kStatsReportTypeTrack report for the new track if there is no // report yet. - StatsMap::iterator it = reports_.find( + StatsReport* found = reports_.Find( StatsId(StatsReport::kStatsReportTypeTrack, audio_track->id())); - if (it == reports_.end()) + if (!found) AddTrackReport(&reports_, audio_track->id()); } @@ -603,49 +601,46 @@ void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track, ASSERT(false); } -bool StatsCollector::GetStats(MediaStreamTrackInterface* track, +void StatsCollector::GetStats(MediaStreamTrackInterface* track, StatsReports* reports) { ASSERT(reports != NULL); - reports->clear(); + ASSERT(reports->empty()); - StatsMap::iterator it; if (!track) { - for (it = reports_.begin(); it != reports_.end(); ++it) { - reports->push_back(it->second); - } - return true; + StatsSet::const_iterator it; + for (it = reports_.begin(); it != reports_.end(); ++it) + reports->push_back(&(*it)); + return; } - it = reports_.find(StatsId(StatsReport::kStatsReportTypeSession, - session_->id())); - if (it != reports_.end()) { - reports->push_back(it->second); - } + StatsReport* report = + reports_.Find(StatsId(StatsReport::kStatsReportTypeSession, + session_->id())); + if (report) + reports->push_back(report); - it = reports_.find(StatsId(StatsReport::kStatsReportTypeTrack, track->id())); + report = reports_.Find( + StatsId(StatsReport::kStatsReportTypeTrack, track->id())); - if (it == reports_.end()) { - LOG(LS_WARNING) << "No StatsReport is available for "<< track->id(); - return false; - } + if (!report) + return; - reports->push_back(it->second); + reports->push_back(report); std::string track_id; - for (it = reports_.begin(); it != reports_.end(); ++it) { - if (it->second.type != StatsReport::kStatsReportTypeSsrc) { + for (StatsSet::const_iterator it = reports_.begin(); it != reports_.end(); + ++it) { + if (it->type != StatsReport::kStatsReportTypeSsrc) continue; - } - if (ExtractValueFromReport(it->second, + + if (ExtractValueFromReport(*it, StatsReport::kStatsValueNameTrackId, &track_id)) { if (track_id == track->id()) { - reports->push_back(it->second); + reports->push_back(&(*it)); } } } - - return true; } void @@ -672,13 +667,13 @@ StatsReport* StatsCollector::PrepareLocalReport( const std::string& transport_id, TrackDirection direction) { const std::string ssrc_id = rtc::ToString<uint32>(ssrc); - StatsMap::iterator it = reports_.find(StatsId( - StatsReport::kStatsReportTypeSsrc, ssrc_id, direction)); + StatsReport* report = reports_.Find( + StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id, direction)); // Use the ID of the track that is currently mapped to the SSRC, if any. std::string track_id; if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { - if (it == reports_.end()) { + if (!report) { // The ssrc is not used by any track or existing report, return NULL // in such case to indicate no report is prepared for the ssrc. return NULL; @@ -686,13 +681,13 @@ StatsReport* StatsCollector::PrepareLocalReport( // The ssrc is not used by any existing track. Keeps the old track id // since we want to report the stats for inactive ssrc. - ExtractValueFromReport(it->second, + ExtractValueFromReport(*report, StatsReport::kStatsValueNameTrackId, &track_id); } - StatsReport* report = GetOrCreateReport(StatsReport::kStatsReportTypeSsrc, - ssrc_id, direction); + report = GetOrCreateReport( + StatsReport::kStatsReportTypeSsrc, ssrc_id, direction); // Clear out stats from previous GatherStats calls if any. // This is required since the report will be returned for the new values. @@ -715,13 +710,13 @@ StatsReport* StatsCollector::PrepareRemoteReport( const std::string& transport_id, TrackDirection direction) { const std::string ssrc_id = rtc::ToString<uint32>(ssrc); - StatsMap::iterator it = reports_.find(StatsId( - StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction)); + StatsReport* report = reports_.Find( + StatsId(StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction)); // Use the ID of the track that is currently mapped to the SSRC, if any. std::string track_id; if (!GetTrackIdBySsrc(ssrc, &track_id, direction)) { - if (it == reports_.end()) { + if (!report) { // The ssrc is not used by any track or existing report, return NULL // in such case to indicate no report is prepared for the ssrc. return NULL; @@ -729,12 +724,12 @@ StatsReport* StatsCollector::PrepareRemoteReport( // The ssrc is not used by any existing track. Keeps the old track id // since we want to report the stats for inactive ssrc. - ExtractValueFromReport(it->second, + ExtractValueFromReport(*report, StatsReport::kStatsValueNameTrackId, &track_id); } - StatsReport* report = GetOrCreateReport( + report = GetOrCreateReport( StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id, direction); // Clear out stats from previous GatherStats calls if any. @@ -778,18 +773,17 @@ std::string StatsCollector::AddOneCertificateReport( rtc::Base64::EncodeFromArray( der_buffer.data(), der_buffer.length(), &der_base64); - StatsReport report; - report.type = StatsReport::kStatsReportTypeCertificate; - report.id = StatsId(report.type, fingerprint); - report.timestamp = stats_gathering_started_; - report.AddValue(StatsReport::kStatsValueNameFingerprint, fingerprint); - report.AddValue(StatsReport::kStatsValueNameFingerprintAlgorithm, - digest_algorithm); - report.AddValue(StatsReport::kStatsValueNameDer, der_base64); + StatsReport* report = reports_.ReplaceOrAddNew( + StatsId(StatsReport::kStatsReportTypeCertificate, fingerprint)); + report->type = StatsReport::kStatsReportTypeCertificate; + report->timestamp = stats_gathering_started_; + report->AddValue(StatsReport::kStatsValueNameFingerprint, fingerprint); + report->AddValue(StatsReport::kStatsValueNameFingerprintAlgorithm, + digest_algorithm); + report->AddValue(StatsReport::kStatsValueNameDer, der_base64); if (!issuer_id.empty()) - report.AddValue(StatsReport::kStatsValueNameIssuerId, issuer_id); - reports_[report.id] = report; - return report.id; + report->AddValue(StatsReport::kStatsValueNameIssuerId, issuer_id); + return report->id; } std::string StatsCollector::AddCertificateReports( @@ -819,15 +813,13 @@ std::string StatsCollector::AddCertificateReports( void StatsCollector::ExtractSessionInfo() { // Extract information from the base session. - StatsReport report; - report.id = StatsId(StatsReport::kStatsReportTypeSession, session_->id()); - report.type = StatsReport::kStatsReportTypeSession; - report.timestamp = stats_gathering_started_; - report.values.clear(); - report.AddBoolean(StatsReport::kStatsValueNameInitiator, - session_->initiator()); - - reports_[report.id] = report; + StatsReport* report = reports_.ReplaceOrAddNew( + StatsId(StatsReport::kStatsReportTypeSession, session_->id())); + report->type = StatsReport::kStatsReportTypeSession; + report->timestamp = stats_gathering_started_; + report->values.clear(); + report->AddBoolean(StatsReport::kStatsValueNameInitiator, + session_->initiator()); cricket::SessionStats stats; if (session_->GetStats(&stats)) { @@ -865,61 +857,58 @@ void StatsCollector::ExtractSessionInfo() { = transport_iter->second.channel_stats.begin(); channel_iter != transport_iter->second.channel_stats.end(); ++channel_iter) { - StatsReport channel_report; std::ostringstream ostc; ostc << "Channel-" << transport_iter->second.content_name << "-" << channel_iter->component; - channel_report.id = ostc.str(); - channel_report.type = StatsReport::kStatsReportTypeComponent; - channel_report.timestamp = stats_gathering_started_; - channel_report.AddValue(StatsReport::kStatsValueNameComponent, - channel_iter->component); + StatsReport* channel_report = reports_.ReplaceOrAddNew(ostc.str()); + channel_report->type = StatsReport::kStatsReportTypeComponent; + channel_report->timestamp = stats_gathering_started_; + channel_report->AddValue(StatsReport::kStatsValueNameComponent, + channel_iter->component); if (!local_cert_report_id.empty()) - channel_report.AddValue( + channel_report->AddValue( StatsReport::kStatsValueNameLocalCertificateId, local_cert_report_id); if (!remote_cert_report_id.empty()) - channel_report.AddValue( + channel_report->AddValue( StatsReport::kStatsValueNameRemoteCertificateId, remote_cert_report_id); - reports_[channel_report.id] = channel_report; for (size_t i = 0; i < channel_iter->connection_infos.size(); ++i) { - StatsReport report; - const cricket::ConnectionInfo& info - = channel_iter->connection_infos[i]; std::ostringstream ost; ost << "Conn-" << transport_iter->first << "-" << channel_iter->component << "-" << i; - report.id = ost.str(); - report.type = StatsReport::kStatsReportTypeCandidatePair; - report.timestamp = stats_gathering_started_; + StatsReport* report = reports_.ReplaceOrAddNew(ost.str()); + report->type = StatsReport::kStatsReportTypeCandidatePair; + report->timestamp = stats_gathering_started_; // Link from connection to its containing channel. - report.AddValue(StatsReport::kStatsValueNameChannelId, - channel_report.id); - report.AddValue(StatsReport::kStatsValueNameBytesSent, - info.sent_total_bytes); - report.AddValue(StatsReport::kStatsValueNameBytesReceived, - info.recv_total_bytes); - report.AddBoolean(StatsReport::kStatsValueNameWritable, - info.writable); - report.AddBoolean(StatsReport::kStatsValueNameReadable, - info.readable); - report.AddBoolean(StatsReport::kStatsValueNameActiveConnection, - info.best_connection); - report.AddValue(StatsReport::kStatsValueNameLocalAddress, - 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()); - report.AddValue(StatsReport::kStatsValueNameLocalCandidateType, - info.local_candidate.type()); - report.AddValue(StatsReport::kStatsValueNameRemoteCandidateType, - info.remote_candidate.type()); - reports_[report.id] = report; + report->AddValue(StatsReport::kStatsValueNameChannelId, + channel_report->id); + + const cricket::ConnectionInfo& info = + channel_iter->connection_infos[i]; + report->AddValue(StatsReport::kStatsValueNameBytesSent, + info.sent_total_bytes); + report->AddValue(StatsReport::kStatsValueNameBytesReceived, + info.recv_total_bytes); + report->AddBoolean(StatsReport::kStatsValueNameWritable, + info.writable); + report->AddBoolean(StatsReport::kStatsValueNameReadable, + info.readable); + report->AddBoolean(StatsReport::kStatsValueNameActiveConnection, + info.best_connection); + report->AddValue(StatsReport::kStatsValueNameLocalAddress, + 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()); + report->AddValue(StatsReport::kStatsValueNameLocalCandidateType, + info.local_candidate.type()); + report->AddValue(StatsReport::kStatsValueNameRemoteCandidateType, + info.remote_candidate.type()); } } } @@ -976,7 +965,8 @@ void StatsCollector::ExtractVideoInfo( if (video_info.bw_estimations.size() != 1) { LOG(LS_ERROR) << "BWEs count: " << video_info.bw_estimations.size(); } else { - StatsReport* report = &reports_[StatsReport::kStatsReportVideoBweId]; + StatsReport* report = + reports_.FindOrAddNew(StatsReport::kStatsReportVideoBweId); ExtractStats( video_info.bw_estimations[0], stats_gathering_started_, level, report); } @@ -987,13 +977,7 @@ StatsReport* StatsCollector::GetReport(const std::string& type, TrackDirection direction) { ASSERT(type == StatsReport::kStatsReportTypeSsrc || type == StatsReport::kStatsReportTypeRemoteSsrc); - std::string statsid = StatsId(type, id, direction); - StatsReport* report = NULL; - std::map<std::string, StatsReport>::iterator it = reports_.find(statsid); - if (it != reports_.end()) - report = &(it->second); - - return report; + return reports_.Find(StatsId(type, id, direction)); } StatsReport* StatsCollector::GetOrCreateReport(const std::string& type, @@ -1004,8 +988,8 @@ StatsReport* StatsCollector::GetOrCreateReport(const std::string& type, StatsReport* report = GetReport(type, id, direction); if (report == NULL) { std::string statsid = StatsId(type, id, direction); - report = &reports_[statsid]; // Create new element. - report->id = statsid; + report = reports_.FindOrAddNew(statsid); + ASSERT(report->id == statsid); report->type = type; } diff --git a/app/webrtc/statscollector.h b/app/webrtc/statscollector.h index a039813..db2d788 100644 --- a/app/webrtc/statscollector.h +++ b/app/webrtc/statscollector.h @@ -72,7 +72,11 @@ class StatsCollector { // be called before this function to get the most recent stats. |selector| is // a track label or empty string. The most recent reports are stored in // |reports|. - bool GetStats(MediaStreamTrackInterface* track, + // TODO(tommi): Change this contract to accept a callback object instead + // of filling in |reports|. As is, there's a requirement that the caller + // uses |reports| immediately without allowing any async activity on + // the thread (message handling etc) and then discard the results. + void GetStats(MediaStreamTrackInterface* track, StatsReports* reports); // Prepare an SSRC report for the given ssrc. Used internally @@ -121,7 +125,7 @@ class StatsCollector { TrackDirection direction); // A map from the report id to the report. - std::map<std::string, StatsReport> reports_; + StatsSet reports_; // Raw pointer to the session the statistics are gathered from. WebRtcSession* const session_; double stats_gathering_started_; diff --git a/app/webrtc/statscollector_unittest.cc b/app/webrtc/statscollector_unittest.cc index f264545..2f4c130 100644 --- a/app/webrtc/statscollector_unittest.cc +++ b/app/webrtc/statscollector_unittest.cc @@ -168,10 +168,10 @@ std::string ExtractStatsValue(const std::string& type, return kNoReports; } for (size_t i = 0; i < reports.size(); ++i) { - if (reports[i].type != type) + if (reports[i]->type != type) continue; std::string ret; - if (GetValue(&reports[i], name, &ret)) { + if (GetValue(reports[i], name, &ret)) { return ret; } } @@ -184,10 +184,10 @@ std::string ExtractStatsValue(const std::string& type, const StatsReport* FindNthReportByType( const StatsReports& reports, const std::string& type, int n) { for (size_t i = 0; i < reports.size(); ++i) { - if (reports[i].type == type) { + if (reports[i]->type == type) { n--; if (n == 0) - return &reports[i]; + return reports[i]; } } return NULL; @@ -196,8 +196,8 @@ const StatsReport* FindNthReportByType( const StatsReport* FindReportById(const StatsReports& reports, const std::string& id) { for (size_t i = 0; i < reports.size(); ++i) { - if (reports[i].id == id) { - return &reports[i]; + if (reports[i]->id == id) { + return reports[i]; } } return NULL; @@ -433,7 +433,7 @@ void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) { class StatsCollectorTest : public testing::Test { protected: StatsCollectorTest() - : media_engine_(new cricket::FakeMediaEngine), + : media_engine_(new cricket::FakeMediaEngine()), channel_manager_( new cricket::ChannelManager(media_engine_, new cricket::FakeDeviceManager(), @@ -443,6 +443,8 @@ class StatsCollectorTest : public testing::Test { EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false)); } + ~StatsCollectorTest() {} + // This creates a standard setup with a transport called "trspname" // having one transport channel // and the specified virtual connection name. @@ -786,7 +788,7 @@ TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) { stats.GetStats(NULL, &reports); EXPECT_EQ((size_t)1, reports.size()); EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack), - reports[0].type); + reports[0]->type); std::string trackValue = ExtractStatsValue(StatsReport::kStatsReportTypeTrack, @@ -832,6 +834,7 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { EXPECT_TRUE(track_report); // Get report for the specific |track|. + reports.clear(); stats.GetStats(track_, &reports); // |reports| should contain at least one session report, one track report, // and one ssrc report. @@ -1396,6 +1399,7 @@ TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) { VerifyVoiceSenderInfoReport(track_report, voice_sender_info); // Get stats for the remote track. + reports.clear(); stats.GetStats(remote_track.get(), &reports); track_report = FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1); @@ -1452,6 +1456,7 @@ TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) { cricket::VoiceSenderInfo new_voice_sender_info; InitVoiceSenderInfo(&new_voice_sender_info); cricket::VoiceMediaInfo new_stats_read; + reports.clear(); SetupAndVerifyAudioTrackStats( new_audio_track.get(), stream_.get(), &stats, &voice_channel, kVcName, media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports); diff --git a/app/webrtc/statstypes.h b/app/webrtc/statstypes.h index 2b1317a..8eae1ad 100644 --- a/app/webrtc/statstypes.h +++ b/app/webrtc/statstypes.h @@ -31,6 +31,7 @@ #ifndef TALK_APP_WEBRTC_STATSTYPES_H_ #define TALK_APP_WEBRTC_STATSTYPES_H_ +#include <set> #include <string> #include <vector> @@ -39,14 +40,49 @@ namespace webrtc { +// TODO(tommi): Move all the implementation that's in this file and +// statscollector.cc related to these types, into a new, statstypes.cc file. + class StatsReport { public: - StatsReport() : timestamp(0) { } + // TODO(tommi): Remove this ctor. + StatsReport() : timestamp(0) {} + + // TODO(tommi): Make protected and disallow copy completely once not needed. + StatsReport(const StatsReport& src) + : id(src.id), + type(src.type), + timestamp(src.timestamp), + values(src.values) {} + + // TODO(tommi): Make this copy constructor protected. + StatsReport& operator=(const StatsReport& src) { + ASSERT(id == src.id); + type = src.type; + timestamp = src.timestamp; + values = src.values; + return *this; + } + + // Constructor is protected to force use of StatsSet. + // TODO(tommi): Make this ctor protected. + explicit StatsReport(const std::string& id) : id(id), timestamp(0) {} + + // Operators provided for STL container/algorithm support. + bool operator<(const StatsReport& other) const { return id < other.id; } + bool operator==(const StatsReport& other) const { return id == other.id; } + // Special support for being able to use std::find on a container + // without requiring a new StatsReport instance. + bool operator==(const std::string& other_id) const { return id == other_id; } // TODO(tommi): Change this to be an enum type that holds all the // kStatsValueName constants. typedef const char* StatsValueName; + // The unique identifier for this object. + // This is used as a key for this report in ordered containers, + // so it must never be changed. + // TODO(tommi): Make this member variable const. std::string id; // See below for contents. std::string type; // See below for contents. @@ -239,7 +275,70 @@ class StatsReport { static const char kStatsValueNameDecodingPLCCNG[]; }; -typedef std::vector<StatsReport> StatsReports; +// This class is provided for the cases where we need to keep +// snapshots of reports around. This is an edge case. +// TODO(tommi): Move into the private section of StatsSet. +class StatsReportCopyable : public StatsReport { + public: + StatsReportCopyable(const std::string& id) : StatsReport(id) {} + explicit StatsReportCopyable(const StatsReport& src) + : StatsReport(src) {} + + using StatsReport::operator=; +}; + +// Typedef for an array of const StatsReport pointers. +// Ownership of the pointers held by this implementation is assumed to lie +// elsewhere and lifetime guarantees are made by the implementation that uses +// this type. In the StatsCollector, object ownership lies with the StatsSet +// class. +typedef std::vector<const StatsReport*> StatsReports; + +// A map from the report id to the report. +// This class wraps an STL container and provides a limited set of +// functionality in order to keep things simple. +// TODO(tommi): Use a thread checker here (currently not in libjingle). +class StatsSet { + public: + StatsSet() {} + ~StatsSet() {} + + typedef std::set<StatsReportCopyable> Container; + typedef Container::iterator iterator; + typedef Container::const_iterator const_iterator; + + const_iterator begin() const { return list_.begin(); } + const_iterator end() const { return list_.end(); } + + // Creates a new report object with |id| that does not already + // exist in the list of reports. + StatsReport* InsertNew(const std::string& id) { + ASSERT(Find(id) == NULL); + const StatsReport* ret = &(*list_.insert(StatsReportCopyable(id)).first); + return const_cast<StatsReport*>(ret); + } + + StatsReport* FindOrAddNew(const std::string& id) { + StatsReport* ret = Find(id); + return ret ? ret : InsertNew(id); + } + + StatsReport* ReplaceOrAddNew(const std::string& id) { + list_.erase(id); + return InsertNew(id); + } + + // Looks for a report with the given |id|. If one is not found, NULL + // will be returned. + StatsReport* Find(const std::string& id) { + const_iterator it = std::find(begin(), end(), id); + return it == end() ? NULL : + const_cast<StatsReport*>(static_cast<const StatsReport*>(&(*it))); + } + + private: + Container list_; +}; } // namespace webrtc diff --git a/app/webrtc/test/mockpeerconnectionobservers.h b/app/webrtc/test/mockpeerconnectionobservers.h index 884c7a8..174b80b 100644 --- a/app/webrtc/test/mockpeerconnectionobservers.h +++ b/app/webrtc/test/mockpeerconnectionobservers.h @@ -120,9 +120,13 @@ class MockStatsObserver : public webrtc::StatsObserver { MockStatsObserver() : called_(false) {} virtual ~MockStatsObserver() {} - virtual void OnComplete(const std::vector<webrtc::StatsReport>& reports) { + virtual void OnComplete(const StatsReports& reports) { called_ = true; - reports_ = reports; + reports_.clear(); + reports_.reserve(reports.size()); + StatsReports::const_iterator it; + for (it = reports.begin(); it != reports.end(); ++it) + reports_.push_back(StatsReportCopyable(*(*it))); } bool called() const { return called_; } @@ -148,7 +152,7 @@ class MockStatsObserver : public webrtc::StatsObserver { } private: - int GetSsrcStatsValue(const std::string name) { + int GetSsrcStatsValue(StatsReport::StatsValueName name) { if (reports_.empty()) { return 0; } @@ -167,7 +171,7 @@ class MockStatsObserver : public webrtc::StatsObserver { } bool called_; - std::vector<webrtc::StatsReport> reports_; + std::vector<StatsReportCopyable> reports_; }; } // namespace webrtc diff --git a/app/webrtc/webrtcsession.cc b/app/webrtc/webrtcsession.cc index 1f14ff7..6d57afb 100644 --- a/app/webrtc/webrtcsession.cc +++ b/app/webrtc/webrtcsession.cc @@ -579,18 +579,6 @@ bool WebRtcSession::Initialize( MediaConstraintsInterface::kPayloadPadding, &video_options_.use_payload_padding); - // Find improved wifi bwe constraint. - if (FindConstraint( - constraints, - MediaConstraintsInterface::kImprovedWifiBwe, - &value, - NULL)) { - video_options_.use_improved_wifi_bandwidth_estimator.Set(value); - } else { - // Enable by default if the constraint is not set. - video_options_.use_improved_wifi_bandwidth_estimator.Set(true); - } - SetOptionFromOptionalConstraint(constraints, MediaConstraintsInterface::kNumUnsignalledRecvStreams, &video_options_.unsignalled_recv_stream_limit); @@ -622,10 +610,6 @@ bool WebRtcSession::Initialize( cricket::VideoOptions::HIGH); } - SetOptionFromOptionalConstraint(constraints, - MediaConstraintsInterface::kOpusFec, - &audio_options_.opus_fec); - const cricket::VideoCodec default_codec( JsepSessionDescription::kDefaultVideoCodecId, JsepSessionDescription::kDefaultVideoCodecName, diff --git a/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java index ef97cda..213da7b 100644 --- a/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java +++ b/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java @@ -200,19 +200,49 @@ public class AppRTCDemoActivity extends Activity private void updateHUD(StatsReport[] reports) { StringBuilder builder = new StringBuilder(); for (StatsReport report : reports) { - if (!report.id.equals("bweforvideo")) { + // bweforvideo to show statistics for video Bandwidth Estimation, + // which is global per-session. + if (report.id.equals("bweforvideo")) { + for (StatsReport.Value value : report.values) { + String name = value.name.replace("goog", "") + .replace("Available", "").replace("Bandwidth", "") + .replace("Bitrate", "").replace("Enc", ""); + + builder.append(name).append("=").append(value.value) + .append(" "); + } + builder.append("\n"); + } else if (report.type.equals("googCandidatePair")) { + String activeConnectionStats = getActiveConnectionStats(report); + if (activeConnectionStats == null) { + continue; + } + builder.append(activeConnectionStats); + } else { continue; } - for (StatsReport.Value value : report.values) { - String name = value.name.replace("goog", "").replace("Available", "") - .replace("Bandwidth", "").replace("Bitrate", "").replace("Enc", ""); - builder.append(name).append("=").append(value.value).append(" "); - } builder.append("\n"); } hudView.setText(builder.toString() + hudView.getText()); } + // Return the active connection stats else return null + private String getActiveConnectionStats(StatsReport report) { + StringBuilder activeConnectionbuilder = new StringBuilder(); + // googCandidatePair to show information about the active + // connection. + for (StatsReport.Value value : report.values) { + if (value.name.equals("googActiveConnection") + && value.value.equals("false")) { + return null; + } + String name = value.name.replace("goog", ""); + activeConnectionbuilder.append(name).append("=") + .append(value.value).append("\n"); + } + return activeConnectionbuilder.toString(); + } + @Override public void onPause() { super.onPause(); diff --git a/examples/call/callclient.cc b/examples/call/callclient.cc index 188f6c4..2c8a6bc 100644 --- a/examples/call/callclient.cc +++ b/examples/call/callclient.cc @@ -1285,8 +1285,9 @@ void CallClient::OnMucStatusUpdate(const buzz::Jid& jid, return; } - if (!status.available()) { - // Remove them from the room. + if (status.available()) { + muc->members()[status.jid().resource()] = status; + } else { muc->members().erase(status.jid().resource()); } } diff --git a/libjingle.gyp b/libjingle.gyp index 6064277..f4f9bf9 100755 --- a/libjingle.gyp +++ b/libjingle.gyp @@ -531,6 +531,7 @@ 'media/webrtc/webrtcexport.h', 'media/webrtc/webrtcmediaengine.cc', 'media/webrtc/webrtcmediaengine.h', + 'media/webrtc/webrtcmediaengine.cc', 'media/webrtc/webrtcpassthroughrender.cc', 'media/webrtc/webrtcpassthroughrender.h', 'media/webrtc/webrtctexturevideoframe.cc', diff --git a/media/base/mediachannel.h b/media/base/mediachannel.h index 3759acc..62d6b61 100644 --- a/media/base/mediachannel.h +++ b/media/base/mediachannel.h @@ -182,7 +182,6 @@ struct AudioOptions { recording_sample_rate.SetFrom(change.recording_sample_rate); playout_sample_rate.SetFrom(change.playout_sample_rate); dscp.SetFrom(change.dscp); - opus_fec.SetFrom(change.opus_fec); } bool operator==(const AudioOptions& o) const { @@ -208,8 +207,7 @@ struct AudioOptions { rx_agc_limiter == o.rx_agc_limiter && recording_sample_rate == o.recording_sample_rate && playout_sample_rate == o.playout_sample_rate && - dscp == o.dscp && - opus_fec == o.opus_fec; + dscp == o.dscp; } std::string ToString() const { @@ -240,7 +238,6 @@ struct AudioOptions { ost << ToStringIfSet("recording_sample_rate", recording_sample_rate); ost << ToStringIfSet("playout_sample_rate", playout_sample_rate); ost << ToStringIfSet("dscp", dscp); - ost << ToStringIfSet("opus_fec", opus_fec); ost << "}"; return ost.str(); } @@ -278,8 +275,6 @@ struct AudioOptions { Settable<uint32> playout_sample_rate; // Set DSCP value for packet sent from audio channel. Settable<bool> dscp; - // Set Opus FEC - Settable<bool> opus_fec; }; // Options that can be applied to a VideoMediaChannel or a VideoMediaEngine. @@ -334,8 +329,6 @@ struct VideoOptions { unsignalled_recv_stream_limit.SetFrom(change.unsignalled_recv_stream_limit); use_simulcast_adapter.SetFrom(change.use_simulcast_adapter); screencast_min_bitrate.SetFrom(change.screencast_min_bitrate); - use_improved_wifi_bandwidth_estimator.SetFrom( - change.use_improved_wifi_bandwidth_estimator); use_payload_padding.SetFrom(change.use_payload_padding); } @@ -372,8 +365,6 @@ struct VideoOptions { unsignalled_recv_stream_limit == o.unsignalled_recv_stream_limit && use_simulcast_adapter == o.use_simulcast_adapter && screencast_min_bitrate == o.screencast_min_bitrate && - use_improved_wifi_bandwidth_estimator == - o.use_improved_wifi_bandwidth_estimator && use_payload_padding == o.use_payload_padding; } @@ -414,8 +405,6 @@ struct VideoOptions { unsignalled_recv_stream_limit); ost << ToStringIfSet("use simulcast adapter", use_simulcast_adapter); ost << ToStringIfSet("screencast min bitrate", screencast_min_bitrate); - ost << ToStringIfSet("improved wifi bwe", - use_improved_wifi_bandwidth_estimator); ost << ToStringIfSet("payload padding", use_payload_padding); ost << "}"; return ost.str(); @@ -488,8 +477,6 @@ struct VideoOptions { Settable<bool> use_simulcast_adapter; // Force screencast to use a minimum bitrate Settable<int> screencast_min_bitrate; - // Enable improved bandwidth estiamtor on wifi. - Settable<bool> use_improved_wifi_bandwidth_estimator; // Enable payload padding. Settable<bool> use_payload_padding; }; diff --git a/media/base/mediaengine.cc b/media/base/mediaengine.cc index 289f229..d38a312 100644 --- a/media/base/mediaengine.cc +++ b/media/base/mediaengine.cc @@ -27,90 +27,40 @@ #include "talk/media/base/mediaengine.h" -namespace cricket { -const int MediaEngineInterface::kDefaultAudioDelayOffset = 0; -} - #if !defined(DISABLE_MEDIA_ENGINE_FACTORY) -#if defined(HAVE_LINPHONE) -#include "talk/media/other/linphonemediaengine.h" -#endif // HAVE_LINPHONE -#if defined(HAVE_WEBRTC_VOICE) -#include "talk/media/webrtc/webrtcvoiceengine.h" -#endif // HAVE_WEBRTC_VOICE -#if defined(HAVE_WEBRTC_VIDEO) -#include "talk/media/webrtc/webrtcvideoengine.h" -#endif // HAVE_WEBRTC_VIDEO -#if defined(HAVE_LMI) -#include "talk/media/base/hybridvideoengine.h" -#include "talk/media/lmi/lmimediaengine.h" -#endif // HAVE_LMI +#if defined(HAVE_WEBRTC_VOICE) && defined(HAVE_WEBRTC_VIDEO) +#include "talk/media/webrtc/webrtcmediaengine.h" +#endif // HAVE_WEBRTC_VOICE && HAVE_WEBRTC_VIDEO + #ifdef HAVE_CONFIG_H #include "config.h" #endif // HAVE_CONFIG namespace cricket { -#if defined(HAVE_WEBRTC_VOICE) -#define AUDIO_ENG_NAME WebRtcVoiceEngine -#else -#define AUDIO_ENG_NAME NullVoiceEngine -#endif - -#if defined(HAVE_WEBRTC_VIDEO) -#if !defined(HAVE_LMI) -template<> -CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine>:: - CompositeMediaEngine() { - video_.SetVoiceEngine(&voice_); -} -#define VIDEO_ENG_NAME WebRtcVideoEngine -#else -// If we have both WebRtcVideoEngine and LmiVideoEngine, enable dual-stack. -// This small class here allows us to hook the WebRtcVideoChannel up to -// the capturer owned by the LMI engine, without infecting the rest of the -// HybridVideoEngine classes with this abstraction violation. -class WebRtcLmiHybridVideoEngine - : public HybridVideoEngine<WebRtcVideoEngine, LmiVideoEngine> { - public: - void SetVoiceEngine(WebRtcVoiceEngine* engine) { - video1_.SetVoiceEngine(engine); - } -}; -template<> -CompositeMediaEngine<WebRtcVoiceEngine, WebRtcLmiHybridVideoEngine>:: - CompositeMediaEngine() { - video_.SetVoiceEngine(&voice_); -} -#define VIDEO_ENG_NAME WebRtcLmiHybridVideoEngine -#endif -#elif defined(HAVE_LMI) -#define VIDEO_ENG_NAME LmiVideoEngine -#else -#define VIDEO_ENG_NAME NullVideoEngine -#endif MediaEngineFactory::MediaEngineCreateFunction MediaEngineFactory::create_function_ = NULL; + MediaEngineFactory::MediaEngineCreateFunction MediaEngineFactory::SetCreateFunction(MediaEngineCreateFunction function) { MediaEngineCreateFunction old_function = create_function_; create_function_ = function; return old_function; -}; +} +// TODO(pthatcher): Remove this method and require all the users of +// media engines to choose one explictly, or at least remove the +// default behavior and require calling SetCreateFunction explictly. MediaEngineInterface* MediaEngineFactory::Create() { if (create_function_) { return create_function_(); - } else { -#if defined(HAVE_LINPHONE) - return new LinphoneMediaEngine("", ""); -#elif defined(AUDIO_ENG_NAME) && defined(VIDEO_ENG_NAME) - return new CompositeMediaEngine<AUDIO_ENG_NAME, VIDEO_ENG_NAME>(); -#else - return new NullMediaEngine(); -#endif } +#if defined(HAVE_WEBRTC_VOICE) && defined(HAVE_WEBRTC_VIDEO) + return WebRtcMediaEngineFactory::Create(); +#else + return new NullMediaEngine(); +#endif // HAVE_WEBRTC_VIDEO && HAVE_WEBRTC_VOICE } }; // namespace cricket diff --git a/media/webrtc/fakewebrtcvideoengine.h b/media/webrtc/fakewebrtcvideoengine.h index 3a9e411..5cba380 100644 --- a/media/webrtc/fakewebrtcvideoengine.h +++ b/media/webrtc/fakewebrtcvideoengine.h @@ -908,6 +908,9 @@ class FakeWebRtcVideoEngine WEBRTC_STUB(SetMTU, (int, unsigned int)); WEBRTC_STUB(ReceivedBWEPacket, (const int, int64_t, int, const webrtc::RTPHeader&)); + virtual bool SetBandwidthEstimationConfig(int, const webrtc::Config&) { + return true; + } // webrtc::ViERender WEBRTC_STUB(RegisterVideoRenderModule, (webrtc::VideoRender&)); diff --git a/media/webrtc/webrtcmediaengine.cc b/media/webrtc/webrtcmediaengine.cc index 445564c..252b4e6 100644 --- a/media/webrtc/webrtcmediaengine.cc +++ b/media/webrtc/webrtcmediaengine.cc @@ -25,8 +25,53 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if defined(LIBPEERCONNECTION_LIB) || \ + defined(LIBPEERCONNECTION_IMPLEMENTATION) + #include "talk/media/webrtc/webrtcmediaengine.h" +#include "talk/media/webrtc/webrtcvideoengine.h" +#ifdef WEBRTC_CHROMIUM_BUILD +#include "talk/media/webrtc/webrtcvideoengine2.h" +#endif +#include "talk/media/webrtc/webrtcvoiceengine.h" +#ifdef WEBRTC_CHROMIUM_BUILD #include "webrtc/system_wrappers/interface/field_trial.h" +#endif + +namespace cricket { + +class WebRtcMediaEngine : + public CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine> { + public: + WebRtcMediaEngine() {} + WebRtcMediaEngine(webrtc::AudioDeviceModule* adm, + webrtc::AudioDeviceModule* adm_sc, + WebRtcVideoEncoderFactory* encoder_factory, + WebRtcVideoDecoderFactory* decoder_factory) { + voice_.SetAudioDeviceModule(adm, adm_sc); + video_.SetVoiceEngine(&voice_); + video_.EnableTimedRender(); + video_.SetExternalEncoderFactory(encoder_factory); + video_.SetExternalDecoderFactory(decoder_factory); + } +}; + +#ifdef WEBRTC_CHROMIUM_BUILD +class WebRtcMediaEngine2 : + public CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine2> { + public: + WebRtcMediaEngine2(webrtc::AudioDeviceModule* adm, + webrtc::AudioDeviceModule* adm_sc, + WebRtcVideoEncoderFactory* encoder_factory, + WebRtcVideoDecoderFactory* decoder_factory) { + voice_.SetAudioDeviceModule(adm, adm_sc); + video_.SetVoiceEngine(&voice_); + video_.EnableTimedRender(); + } +}; +#endif // WEBRTC_CHROMIUM_BUILD + +} // namespace cricket WRME_EXPORT cricket::MediaEngineInterface* CreateWebRtcMediaEngine( @@ -40,19 +85,35 @@ cricket::MediaEngineInterface* CreateWebRtcMediaEngine( adm, adm_sc, encoder_factory, decoder_factory); } #endif // WEBRTC_CHROMIUM_BUILD + // This is just to get a diff to run pulse. return new cricket::WebRtcMediaEngine( adm, adm_sc, encoder_factory, decoder_factory); } WRME_EXPORT void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) { -#ifdef WEBRTC_CHROMIUM_BUILD - if (webrtc::field_trial::FindFullName("WebRTC-NewVideoAPI") == "Enabled") { - delete static_cast<cricket::WebRtcMediaEngine2*>(media_engine); - } else { -#endif // WEBRTC_CHROMIUM_BUILD - delete static_cast<cricket::WebRtcMediaEngine*>(media_engine); -#ifdef WEBRTC_CHROMIUM_BUILD - } -#endif // WEBRTC_CHROMIUM_BUILD + delete media_engine; +} + +namespace cricket { + +// Used by ChannelManager when no media engine is passed in to it +// explicitly (acts as a default). +MediaEngineInterface* WebRtcMediaEngineFactory::Create() { + return new cricket::WebRtcMediaEngine(); } + +// Used by PeerConnectionFactory to create a media engine passed into +// ChannelManager. +MediaEngineInterface* WebRtcMediaEngineFactory::Create( + webrtc::AudioDeviceModule* adm, + webrtc::AudioDeviceModule* adm_sc, + WebRtcVideoEncoderFactory* encoder_factory, + WebRtcVideoDecoderFactory* decoder_factory) { + return CreateWebRtcMediaEngine(adm, adm_sc, encoder_factory, decoder_factory); +} + +} // namespace cricket + +#endif // defined(LIBPEERCONNECTION_LIB) || + // defined(LIBPEERCONNECTION_IMPLEMENTATION) diff --git a/media/webrtc/webrtcmediaengine.h b/media/webrtc/webrtcmediaengine.h index 701417c..b906f5d 100644 --- a/media/webrtc/webrtcmediaengine.h +++ b/media/webrtc/webrtcmediaengine.h @@ -40,7 +40,6 @@ class WebRtcVideoDecoderFactory; class WebRtcVideoEncoderFactory; } - #if !defined(LIBPEERCONNECTION_LIB) && \ !defined(LIBPEERCONNECTION_IMPLEMENTATION) @@ -53,19 +52,49 @@ cricket::MediaEngineInterface* CreateWebRtcMediaEngine( WRME_EXPORT void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine); +#endif // !defined(LIBPEERCONNECTION_LIB) && + // !defined(LIBPEERCONNECTION_IMPLEMENTATION) + namespace cricket { -class WebRtcMediaEngine : public cricket::MediaEngineInterface { +class WebRtcMediaEngineFactory { public: - WebRtcMediaEngine( +#if !defined(LIBPEERCONNECTION_LIB) && \ + !defined(LIBPEERCONNECTION_IMPLEMENTATION) +// A bare Create() isn't supported when using the delegating media +// engine. +#else + static MediaEngineInterface* Create(); +#endif // !defined(LIBPEERCONNECTION_LIB) && + // !defined(LIBPEERCONNECTION_IMPLEMENTATION) + static MediaEngineInterface* Create( webrtc::AudioDeviceModule* adm, webrtc::AudioDeviceModule* adm_sc, - cricket::WebRtcVideoEncoderFactory* encoder_factory, - cricket::WebRtcVideoDecoderFactory* decoder_factory) + WebRtcVideoEncoderFactory* encoder_factory, + WebRtcVideoDecoderFactory* decoder_factory); +}; + +} // namespace cricket + + +#if !defined(LIBPEERCONNECTION_LIB) && \ + !defined(LIBPEERCONNECTION_IMPLEMENTATION) + +namespace cricket { + +// TODO(pthacther): Move this code into webrtcmediaengine.cc once +// Chrome compiles it. Right now it relies on only the .h file. +class DelegatingWebRtcMediaEngine : public cricket::MediaEngineInterface { + public: + DelegatingWebRtcMediaEngine( + webrtc::AudioDeviceModule* adm, + webrtc::AudioDeviceModule* adm_sc, + WebRtcVideoEncoderFactory* encoder_factory, + WebRtcVideoDecoderFactory* decoder_factory) : delegate_(CreateWebRtcMediaEngine( adm, adm_sc, encoder_factory, decoder_factory)) { } - virtual ~WebRtcMediaEngine() { + virtual ~DelegatingWebRtcMediaEngine() { DestroyWebRtcMediaEngine(delegate_); } virtual bool Init(rtc::Thread* worker_thread) OVERRIDE { @@ -171,49 +200,16 @@ class WebRtcMediaEngine : public cricket::MediaEngineInterface { cricket::MediaEngineInterface* delegate_; }; -} // namespace cricket -#else - -#include "talk/media/webrtc/webrtcvideoengine.h" -#ifdef WEBRTC_CHROMIUM_BUILD -#include "talk/media/webrtc/webrtcvideoengine2.h" -#endif -#include "talk/media/webrtc/webrtcvoiceengine.h" - -namespace cricket { -typedef CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine> - WebRtcCompositeMediaEngine; - -class WebRtcMediaEngine : public WebRtcCompositeMediaEngine { - public: - WebRtcMediaEngine(webrtc::AudioDeviceModule* adm, - webrtc::AudioDeviceModule* adm_sc, - WebRtcVideoEncoderFactory* encoder_factory, - WebRtcVideoDecoderFactory* decoder_factory) { - voice_.SetAudioDeviceModule(adm, adm_sc); - video_.SetVoiceEngine(&voice_); - video_.EnableTimedRender(); - video_.SetExternalEncoderFactory(encoder_factory); - video_.SetExternalDecoderFactory(decoder_factory); - } -}; - -#ifdef WEBRTC_CHROMIUM_BUILD -typedef CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine2> - WebRtcCompositeMediaEngine2; - -class WebRtcMediaEngine2 : public WebRtcCompositeMediaEngine2 { - public: - WebRtcMediaEngine2(webrtc::AudioDeviceModule* adm, - webrtc::AudioDeviceModule* adm_sc, - WebRtcVideoEncoderFactory* encoder_factory, - WebRtcVideoDecoderFactory* decoder_factory) { - voice_.SetAudioDeviceModule(adm, adm_sc); - video_.SetVoiceEngine(&voice_); - video_.EnableTimedRender(); - } -}; -#endif +// Used by PeerConnectionFactory to create a media engine passed into +// ChannelManager. +MediaEngineInterface* WebRtcMediaEngineFactory::Create( + webrtc::AudioDeviceModule* adm, + webrtc::AudioDeviceModule* adm_sc, + WebRtcVideoEncoderFactory* encoder_factory, + WebRtcVideoDecoderFactory* decoder_factory) { + return new cricket::DelegatingWebRtcMediaEngine( + adm, adm_sc, encoder_factory, decoder_factory); +} } // namespace cricket diff --git a/media/webrtc/webrtcvideoengine.cc b/media/webrtc/webrtcvideoengine.cc index 6ba48a7..83b1177 100644 --- a/media/webrtc/webrtcvideoengine.cc +++ b/media/webrtc/webrtcvideoengine.cc @@ -2958,11 +2958,6 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) { conference_mode_turned_off = true; } - bool improved_wifi_bwe_changed = - options.use_improved_wifi_bandwidth_estimator.IsSet() && - options_.use_improved_wifi_bandwidth_estimator != - options.use_improved_wifi_bandwidth_estimator; - #ifdef USE_WEBRTC_DEV_BRANCH bool payload_padding_changed = options.use_payload_padding.IsSet() && options_.use_payload_padding != options.use_payload_padding; @@ -3070,18 +3065,6 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) { LOG(LS_WARNING) << "Cannot disable video suspension once it is enabled"; } } - if (improved_wifi_bwe_changed) { - LOG(LS_INFO) << "Improved WIFI BWE called."; - webrtc::Config config; - config.Set(new webrtc::AimdRemoteRateControl( - options_.use_improved_wifi_bandwidth_estimator - .GetWithDefaultIfUnset(false))); - for (SendChannelMap::iterator it = send_channels_.begin(); - it != send_channels_.end(); ++it) { - engine()->vie()->network()->SetBandwidthEstimationConfig( - it->second->channel_id(), config); - } - } #ifdef USE_WEBRTC_DEV_BRANCH if (payload_padding_changed) { LOG(LS_INFO) << "Payload-based padding called."; @@ -3602,6 +3585,16 @@ bool WebRtcVideoMediaChannel::ConfigureSending(int channel_id, return false; } + // Enable improved WiFi Bandwidth Estimation + { + webrtc::Config config; + config.Set(new webrtc::AimdRemoteRateControl(true)); + if (!engine()->vie()->network()->SetBandwidthEstimationConfig(channel_id, + config)) { + return false; + } + } + send_channels_[local_ssrc_key] = send_channel.release(); return true; diff --git a/media/webrtc/webrtcvideoengine2.cc b/media/webrtc/webrtcvideoengine2.cc index 5bb9db4..ea53596 100644 --- a/media/webrtc/webrtcvideoengine2.cc +++ b/media/webrtc/webrtcvideoengine2.cc @@ -59,17 +59,14 @@ static const int kDefaultRtcpReceiverReportSsrc = 1; struct VideoCodecPref { int payload_type; + int width; + int height; const char* name; int rtx_payload_type; -} kDefaultVideoCodecPref = {100, kVp8CodecName, 96}; +} kDefaultVideoCodecPref = {100, 640, 400, kVp8CodecName, 96}; -VideoCodecPref kRedPref = {116, kRedCodecName, -1}; -VideoCodecPref kUlpfecPref = {117, kUlpfecCodecName, -1}; - -// The formats are sorted by the descending order of width. We use the order to -// find the next format for CPU and bandwidth adaptation. -const VideoFormatPod kDefaultMaxVideoFormat = { - 640, 400, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY}; +VideoCodecPref kRedPref = {116, -1, -1, kRedCodecName, -1}; +VideoCodecPref kUlpfecPref = {117, -1, -1, kUlpfecCodecName, -1}; static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs, const VideoCodec& requested_codec, @@ -107,8 +104,8 @@ static bool IsRembEnabled(const VideoCodec& codec) { static VideoCodec DefaultVideoCodec() { VideoCodec default_codec(kDefaultVideoCodecPref.payload_type, kDefaultVideoCodecPref.name, - kDefaultMaxVideoFormat.width, - kDefaultMaxVideoFormat.height, + kDefaultVideoCodecPref.width, + kDefaultVideoCodecPref.height, kDefaultFramerate, 0); AddDefaultFeedbackParams(&default_codec); @@ -285,13 +282,21 @@ void DefaultUnsignalledSsrcHandler::SetDefaultRenderer( } } -WebRtcVideoEngine2::WebRtcVideoEngine2() { +WebRtcVideoEngine2::WebRtcVideoEngine2() + : default_codec_format_(kDefaultVideoCodecPref.width, + kDefaultVideoCodecPref.height, + FPS_TO_INTERVAL(kDefaultFramerate), + FOURCC_ANY) { // Construct without a factory or voice engine. Construct(NULL, NULL, new rtc::CpuMonitor(NULL)); } WebRtcVideoEngine2::WebRtcVideoEngine2( - WebRtcVideoChannelFactory* channel_factory) { + WebRtcVideoChannelFactory* channel_factory) + : default_codec_format_(kDefaultVideoCodecPref.width, + kDefaultVideoCodecPref.height, + FPS_TO_INTERVAL(kDefaultFramerate), + FOURCC_ANY) { // Construct without a voice engine. Construct(channel_factory, NULL, new rtc::CpuMonitor(NULL)); } @@ -308,7 +313,6 @@ void WebRtcVideoEngine2::Construct(WebRtcVideoChannelFactory* channel_factory, channel_factory_ = channel_factory; video_codecs_ = DefaultVideoCodecs(); - default_codec_format_ = VideoFormat(kDefaultMaxVideoFormat); rtp_header_extensions_.push_back( RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, diff --git a/media/webrtc/webrtcvoiceengine.cc b/media/webrtc/webrtcvoiceengine.cc index 81a6cdc..5cf53e4 100644 --- a/media/webrtc/webrtcvoiceengine.cc +++ b/media/webrtc/webrtcvoiceengine.cc @@ -237,7 +237,6 @@ static AudioOptions GetDefaultEngineOptions() { options.experimental_aec.Set(false); options.experimental_ns.Set(false); options.aec_dump.Set(false); - options.opus_fec.Set(false); return options; } @@ -430,15 +429,6 @@ static bool IsOpusFecEnabled(const AudioCodec& codec) { return codec.GetParam(kCodecParamUseInbandFec, &value) && value == 1; } -// Set params[kCodecParamUseInbandFec]. Caller should make sure codec is Opus. -static void SetOpusFec(AudioCodec* codec, bool opus_fec) { - if (opus_fec) { - codec->SetParam(kCodecParamUseInbandFec, 1); - } else { - codec->RemoveParam(kCodecParamUseInbandFec); - } -} - void WebRtcVoiceEngine::ConstructCodecs() { LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; int ncodecs = voe_wrapper_->codec()->NumOfCodecs(); @@ -483,7 +473,6 @@ void WebRtcVoiceEngine::ConstructCodecs() { } // TODO(hellner): Add ptime, sprop-stereo, stereo and useinbandfec // when they can be set to values other than the default. - SetOpusFec(&codec, false); } codecs_.push_back(codec); } else { @@ -916,16 +905,6 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { } } - bool opus_fec; - if (options.opus_fec.Get(&opus_fec)) { - LOG(LS_INFO) << "Opus FEC is enabled? " << opus_fec; - for (std::vector<AudioCodec>::iterator it = codecs_.begin(); - it != codecs_.end(); ++it) { - if (IsOpus(*it)) - SetOpusFec(&(*it), opus_fec); - } - } - return true; } diff --git a/media/webrtc/webrtcvoiceengine_unittest.cc b/media/webrtc/webrtcvoiceengine_unittest.cc index 1798d1d..89d4c4d 100644 --- a/media/webrtc/webrtcvoiceengine_unittest.cc +++ b/media/webrtc/webrtcvoiceengine_unittest.cc @@ -1230,31 +1230,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecIsacWithParamNoFec) { } #endif // USE_WEBRTC_DEV_BRANCH -// Test AudioOptions controls whether opus FEC is supported in codec list. -TEST_F(WebRtcVoiceEngineTestFake, OpusFecViaOptions) { - EXPECT_TRUE(SetupEngine()); - std::vector<cricket::AudioCodec> codecs = engine_.codecs(); - int value; - for (std::vector<cricket::AudioCodec>::const_iterator it = codecs.begin(); - it != codecs.end(); ++it) { - if (_stricmp(it->name.c_str(), cricket::kOpusCodecName) == 0) { - EXPECT_FALSE(it->GetParam(cricket::kCodecParamUseInbandFec, &value)); - } - } - - cricket::AudioOptions options; - options.opus_fec.Set(true); - EXPECT_TRUE(engine_.SetOptions(options)); - codecs = engine_.codecs(); - for (std::vector<cricket::AudioCodec>::const_iterator it = codecs.begin(); - it != codecs.end(); ++it) { - if (_stricmp(it->name.c_str(), cricket::kOpusCodecName) == 0) { - EXPECT_TRUE(it->GetParam(cricket::kCodecParamUseInbandFec, &value)); - EXPECT_EQ(1, value); - } - } -} - // Test that we can apply CELT with stereo mode but fail with mono mode. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCelt) { EXPECT_TRUE(SetupEngine()); diff --git a/p2p/base/dtlstransportchannel.cc b/p2p/base/dtlstransportchannel.cc index c41d383..e0f4141 100644 --- a/p2p/base/dtlstransportchannel.cc +++ b/p2p/base/dtlstransportchannel.cc @@ -298,6 +298,11 @@ bool DtlsTransportChannelWrapper::SetSrtpCiphers( if (srtp_ciphers_ == ciphers) return true; + if (dtls_state_ == STATE_STARTED) { + LOG(LS_WARNING) << "Ignoring new SRTP ciphers while DTLS is negotiating"; + return true; + } + if (dtls_state_ == STATE_OPEN) { // We don't support DTLS renegotiation currently. If new set of srtp ciphers // are different than what's being used currently, we will not use it. diff --git a/p2p/base/turnport_unittest.cc b/p2p/base/turnport_unittest.cc index 4582dc0..44dc64f 100644 --- a/p2p/base/turnport_unittest.cc +++ b/p2p/base/turnport_unittest.cc @@ -378,7 +378,7 @@ TEST_F(TurnPortTest, TestTurnTcpAllocate) { // Testing turn port will attempt to create TCP socket on address resolution // failure. -TEST_F(TurnPortTest, TestTurnTcpOnAddressResolveFailure) { +TEST_F(TurnPortTest, DISABLED_TestTurnTcpOnAddressResolveFailure) { turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, cricket::ProtocolAddress( rtc::SocketAddress("www.webrtc-blah-blah.com", 3478), @@ -393,7 +393,7 @@ TEST_F(TurnPortTest, TestTurnTcpOnAddressResolveFailure) { // In case of UDP on address resolve failure, TurnPort will not create socket // and return allocate failure. -TEST_F(TurnPortTest, TestTurnUdpOnAdressResolveFailure) { +TEST_F(TurnPortTest, DISABLED_TestTurnUdpOnAdressResolveFailure) { CreateTurnPort(kTurnUsername, kTurnPassword, cricket::ProtocolAddress( rtc::SocketAddress("www.webrtc-blah-blah.com", 3478), cricket::PROTO_UDP)); diff --git a/session/media/channelmanager.cc b/session/media/channelmanager.cc index 8ceb148..a1cdcc0 100644 --- a/session/media/channelmanager.cc +++ b/session/media/channelmanager.cc @@ -120,7 +120,7 @@ void ChannelManager::Construct(MediaEngineInterface* me, audio_options_ = media_engine_->GetAudioOptions(); audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName; audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName; - audio_delay_offset_ = MediaEngineInterface::kDefaultAudioDelayOffset; + audio_delay_offset_ = kDefaultAudioDelayOffset; audio_output_volume_ = kNotSetOutputVolume; local_renderer_ = NULL; capturing_ = false; diff --git a/session/media/channelmanager.h b/session/media/channelmanager.h index e13ae12..f7a2890 100644 --- a/session/media/channelmanager.h +++ b/session/media/channelmanager.h @@ -42,6 +42,8 @@ namespace cricket { +const int kDefaultAudioDelayOffset = 0; + class Soundclip; class VideoProcessor; class VoiceChannel; diff --git a/session/media/channelmanager_unittest.cc b/session/media/channelmanager_unittest.cc index 3896112..f234732 100644 --- a/session/media/channelmanager_unittest.cc +++ b/session/media/channelmanager_unittest.cc @@ -267,7 +267,7 @@ TEST_F(ChannelManagerTest, SetAudioOptionsBeforeInit) { EXPECT_EQ(options, set_options); // At this point, the media engine should also be initialized. EXPECT_EQ(options, fme_->audio_options()); - EXPECT_EQ(cricket::MediaEngineInterface::kDefaultAudioDelayOffset, + EXPECT_EQ(cricket::kDefaultAudioDelayOffset, fme_->audio_delay_offset()); } @@ -294,7 +294,7 @@ TEST_F(ChannelManagerTest, SetAudioOptions) { fme_->audio_in_device()); EXPECT_EQ(std::string(cricket::DeviceManagerInterface::kDefaultDeviceName), fme_->audio_out_device()); - EXPECT_EQ(cricket::MediaEngineInterface::kDefaultAudioDelayOffset, + EXPECT_EQ(cricket::kDefaultAudioDelayOffset, fme_->audio_delay_offset()); // Test setting specific values. AudioOptions options; @@ -306,7 +306,7 @@ TEST_F(ChannelManagerTest, SetAudioOptions) { EXPECT_TRUE( fme_->audio_options().auto_gain_control.Get(&auto_gain_control)); EXPECT_TRUE(auto_gain_control); - EXPECT_EQ(cricket::MediaEngineInterface::kDefaultAudioDelayOffset, + EXPECT_EQ(cricket::kDefaultAudioDelayOffset, fme_->audio_delay_offset()); // Test setting bad values. EXPECT_FALSE(cm_->SetAudioOptions("audio-in9", "audio-out2", options)); |