зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1359775
- Part 1 - add RTCRtpContributingSourceStats;r=jib,smaug
Still left TODO: * add an aboutWebrtc.js section * write tests MozReview-Commit-ID: DwFxq19KWeu --HG-- extra : rebase_source : fad3018d851316af83df48c62db16028a1a84b5c
This commit is contained in:
Родитель
d2076c357d
Коммит
e45ddffb1e
|
@ -15,6 +15,7 @@ function convertToRTCStatsReport(dict) {
|
|||
let report = {};
|
||||
appendStats(dict.inboundRTPStreamStats, report);
|
||||
appendStats(dict.outboundRTPStreamStats, report);
|
||||
appendStats(dict.rtpContributingSourceStats, report);
|
||||
appendStats(dict.mediaStreamTrackStats, report);
|
||||
appendStats(dict.mediaStreamStats, report);
|
||||
appendStats(dict.transportStats, report);
|
||||
|
|
|
@ -35,6 +35,7 @@ var statsExpectedByType = {
|
|||
"sliCount", "qpSum", "targetBitrate",],
|
||||
deprecated: [],
|
||||
},
|
||||
"csrc": { skip: true },
|
||||
"codec": { skip: true },
|
||||
"peer-connection": { skip: true },
|
||||
"data-channel": { skip: true },
|
||||
|
|
|
@ -115,6 +115,7 @@ struct ParamTraits<mozilla::dom::RTCStatsReportInternal>
|
|||
WriteParam(aMsg, aParam.mIceRestarts);
|
||||
WriteParam(aMsg, aParam.mIceRollbacks);
|
||||
WriteParam(aMsg, aParam.mTransportStats);
|
||||
WriteParam(aMsg, aParam.mRtpContributingSourceStats);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
|
@ -134,7 +135,8 @@ struct ParamTraits<mozilla::dom::RTCStatsReportInternal>
|
|||
!ReadParam(aMsg, aIter, &(aResult->mTimestamp)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mIceRestarts)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mIceRollbacks)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mTransportStats))) {
|
||||
!ReadParam(aMsg, aIter, &(aResult->mTransportStats)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mRtpContributingSourceStats))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -504,6 +506,29 @@ struct ParamTraits<mozilla::dom::RTCMediaStreamTrackStats>
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::dom::RTCRTPContributingSourceStats>
|
||||
{
|
||||
typedef mozilla::dom::RTCRTPContributingSourceStats paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mContributorSsrc);
|
||||
WriteParam(aMsg, aParam.mInboundRtpStreamId);
|
||||
WriteRTCStats(aMsg, aParam);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
if (!ReadParam(aMsg, aIter, &(aResult->mContributorSsrc)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mInboundRtpStreamId)) ||
|
||||
!ReadRTCStats(aMsg, aIter, aResult)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
#endif // _WEBRTC_GLOBAL_H_
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
enum RTCStatsType {
|
||||
"inbound-rtp",
|
||||
"outbound-rtp",
|
||||
"csrc",
|
||||
"session",
|
||||
"track",
|
||||
"transport",
|
||||
|
@ -95,6 +96,11 @@ dictionary RTCMediaStreamStats : RTCStats {
|
|||
sequence<DOMString> trackIds; // Note: stats object ids, not track.id
|
||||
};
|
||||
|
||||
dictionary RTCRTPContributingSourceStats : RTCStats {
|
||||
unsigned long contributorSsrc;
|
||||
DOMString inboundRtpStreamId;
|
||||
};
|
||||
|
||||
dictionary RTCTransportStats: RTCStats {
|
||||
unsigned long bytesSent;
|
||||
unsigned long bytesReceived;
|
||||
|
@ -157,22 +163,23 @@ dictionary RTCCodecStats : RTCStats {
|
|||
// to be received from c++
|
||||
|
||||
dictionary RTCStatsReportInternal {
|
||||
DOMString pcid = "";
|
||||
sequence<RTCInboundRTPStreamStats> inboundRTPStreamStats;
|
||||
sequence<RTCOutboundRTPStreamStats> outboundRTPStreamStats;
|
||||
sequence<RTCMediaStreamTrackStats> mediaStreamTrackStats;
|
||||
sequence<RTCMediaStreamStats> mediaStreamStats;
|
||||
sequence<RTCTransportStats> transportStats;
|
||||
sequence<RTCIceComponentStats> iceComponentStats;
|
||||
sequence<RTCIceCandidatePairStats> iceCandidatePairStats;
|
||||
sequence<RTCIceCandidateStats> iceCandidateStats;
|
||||
sequence<RTCCodecStats> codecStats;
|
||||
DOMString localSdp;
|
||||
DOMString remoteSdp;
|
||||
DOMHighResTimeStamp timestamp;
|
||||
unsigned long iceRestarts;
|
||||
unsigned long iceRollbacks;
|
||||
boolean closed; // Is the PC now closed
|
||||
DOMString pcid = "";
|
||||
sequence<RTCInboundRTPStreamStats> inboundRTPStreamStats;
|
||||
sequence<RTCOutboundRTPStreamStats> outboundRTPStreamStats;
|
||||
sequence<RTCRTPContributingSourceStats> rtpContributingSourceStats;
|
||||
sequence<RTCMediaStreamTrackStats> mediaStreamTrackStats;
|
||||
sequence<RTCMediaStreamStats> mediaStreamStats;
|
||||
sequence<RTCTransportStats> transportStats;
|
||||
sequence<RTCIceComponentStats> iceComponentStats;
|
||||
sequence<RTCIceCandidatePairStats> iceCandidatePairStats;
|
||||
sequence<RTCIceCandidateStats> iceCandidateStats;
|
||||
sequence<RTCCodecStats> codecStats;
|
||||
DOMString localSdp;
|
||||
DOMString remoteSdp;
|
||||
DOMHighResTimeStamp timestamp;
|
||||
unsigned long iceRestarts;
|
||||
unsigned long iceRollbacks;
|
||||
boolean closed; // Is the PC now closed
|
||||
};
|
||||
|
||||
[Pref="media.peerconnection.enabled",
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "transportlayerice.h"
|
||||
#include "runnable_utils.h"
|
||||
#include "libyuv/convert.h"
|
||||
#include "mozilla/dom/RTCStatsReportBinding.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "mozilla/PeerIdentity.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
@ -56,6 +57,8 @@
|
|||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
// Max size given stereo is 480*2*2 = 1920 (10ms of 16-bits stereo audio at
|
||||
|
@ -609,7 +612,7 @@ MediaPipeline::MediaPipeline(const std::string& pc,
|
|||
pc_(pc),
|
||||
description_(),
|
||||
filter_(filter),
|
||||
rtp_parser_(webrtc::RtpHeaderParser::Create()) {
|
||||
rtp_parser_(webrtc::RtpHeaderParser::Create()){
|
||||
// To indicate rtcp-mux rtcp_transport should be nullptr.
|
||||
// Therefore it's an error to send in the same flow for
|
||||
// both rtp and rtcp.
|
||||
|
@ -769,6 +772,22 @@ MediaPipeline::AddRIDFilter_s(const std::string& rid)
|
|||
filter_->AddRemoteRtpStreamId(rid);
|
||||
}
|
||||
|
||||
void
|
||||
MediaPipeline::GetContributingSourceStats(
|
||||
const nsString& aInboundRtpStreamId,
|
||||
FallibleTArray<dom::RTCRTPContributingSourceStats>& aArr) const
|
||||
{
|
||||
// Get the expiry from now
|
||||
DOMHighResTimeStamp expiry = RtpCSRCStats::GetExpiryFromTime(GetNow());
|
||||
for (auto info : csrc_stats_) {
|
||||
if (!info.second.Expired(expiry)) {
|
||||
RTCRTPContributingSourceStats stats;
|
||||
info.second.GetWebidlInstance(stats, aInboundRtpStreamId);
|
||||
aArr.AppendElement(stats, fallible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPipeline::StateChange(TransportFlow *flow, TransportLayer::State state) {
|
||||
TransportInfo* info = GetTransportInfo_s(flow);
|
||||
MOZ_ASSERT(info);
|
||||
|
@ -1063,6 +1082,44 @@ void MediaPipeline::RtpPacketReceived(TransportLayer *layer,
|
|||
return;
|
||||
}
|
||||
|
||||
// Make sure to only get the time once, and only if we need it by
|
||||
// using getTimestamp() for access
|
||||
DOMHighResTimeStamp now = 0.0;
|
||||
bool hasTime = false;
|
||||
|
||||
// Remove expired RtpCSRCStats
|
||||
if (!csrc_stats_.empty()) {
|
||||
if (!hasTime) {
|
||||
now = GetNow();
|
||||
hasTime = true;
|
||||
}
|
||||
auto expiry = RtpCSRCStats::GetExpiryFromTime(now);
|
||||
for (auto p = csrc_stats_.begin(); p != csrc_stats_.end();) {
|
||||
if (p->second.Expired(expiry)) {
|
||||
p = csrc_stats_.erase(p);
|
||||
continue;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
// Add new RtpCSRCStats
|
||||
if (header.numCSRCs) {
|
||||
for (auto i = 0; i < header.numCSRCs; i++) {
|
||||
if (!hasTime) {
|
||||
now = GetNow();
|
||||
hasTime = true;
|
||||
}
|
||||
auto csrcInfo = csrc_stats_.find(header.arrOfCSRCs[i]);
|
||||
if (csrcInfo == csrc_stats_.end()) {
|
||||
csrc_stats_.insert(std::make_pair(header.arrOfCSRCs[i],
|
||||
RtpCSRCStats(header.arrOfCSRCs[i],now)));
|
||||
} else {
|
||||
csrcInfo->second.SetTimestamp(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make a copy rather than cast away constness
|
||||
auto inner_data = MakeUnique<unsigned char[]>(len);
|
||||
memcpy(inner_data.get(), data, len);
|
||||
|
@ -2322,4 +2379,35 @@ void MediaPipelineReceiveVideo::SetPrincipalHandle_m(const PrincipalHandle& prin
|
|||
listener_->SetPrincipalHandle_m(principal_handle);
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp MediaPipeline::GetNow() {
|
||||
return webrtc::Clock::GetRealTimeClock()->TimeInMilliseconds();
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
MediaPipeline::RtpCSRCStats::GetExpiryFromTime(
|
||||
const DOMHighResTimeStamp aTime) {
|
||||
// DOMHighResTimeStamp is a unit measured in ms
|
||||
return aTime - EXPIRY_TIME_MILLISECONDS;
|
||||
}
|
||||
|
||||
MediaPipeline::RtpCSRCStats::RtpCSRCStats(const uint32_t aCsrc,
|
||||
const DOMHighResTimeStamp aTime)
|
||||
: mCsrc(aCsrc)
|
||||
, mTimestamp(aTime) {}
|
||||
|
||||
void
|
||||
MediaPipeline::RtpCSRCStats::GetWebidlInstance(
|
||||
dom::RTCRTPContributingSourceStats& aWebidlObj,
|
||||
const nsString &aInboundRtpStreamId) const
|
||||
{
|
||||
nsString statId = NS_LITERAL_STRING("csrc_") + aInboundRtpStreamId;
|
||||
statId.AppendLiteral("_");
|
||||
statId.AppendInt(mCsrc);
|
||||
aWebidlObj.mId.Construct(statId);
|
||||
aWebidlObj.mType.Construct(RTCStatsType::Csrc);
|
||||
aWebidlObj.mTimestamp.Construct(mTimestamp);
|
||||
aWebidlObj.mContributorSsrc.Construct(mCsrc);
|
||||
aWebidlObj.mInboundRtpStreamId.Construct(aInboundRtpStreamId);
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#ifndef mediapipeline_h__
|
||||
#define mediapipeline_h__
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "sigslot.h"
|
||||
|
||||
#include "MediaConduitInterface.h"
|
||||
|
@ -36,6 +38,7 @@ class VideoFrameConverter;
|
|||
|
||||
namespace dom {
|
||||
class MediaStreamTrack;
|
||||
struct RTCRTPContributingSourceStats;
|
||||
} // namespace dom
|
||||
|
||||
class SourceMediaStream;
|
||||
|
@ -132,6 +135,45 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
return (rtp_.type_ == MUX);
|
||||
}
|
||||
|
||||
class RtpCSRCStats {
|
||||
public:
|
||||
// Gets an expiration time for CRC info given a reference time,
|
||||
// this reference time would normally be the time of calling.
|
||||
// This value can then be used to check if a RtpCSRCStats
|
||||
// has expired via Expired(...)
|
||||
static DOMHighResTimeStamp
|
||||
GetExpiryFromTime(const DOMHighResTimeStamp aTime);
|
||||
|
||||
RtpCSRCStats(const uint32_t aCsrc,
|
||||
const DOMHighResTimeStamp aTime);
|
||||
~RtpCSRCStats() {};
|
||||
// Initialize a webidl representation suitable for adding to a report.
|
||||
// This assumes that the webidl object is empty.
|
||||
// @param aWebidlObj the webidl binding object to popluate
|
||||
// @param aRtpInboundStreamId the associated RTCInboundRTPStreamStats.id
|
||||
void
|
||||
GetWebidlInstance(dom::RTCRTPContributingSourceStats& aWebidlObj,
|
||||
const nsString &aInboundRtpStreamId) const;
|
||||
void SetTimestamp(const DOMHighResTimeStamp aTime) { mTimestamp = aTime; }
|
||||
// Check if the RtpCSRCStats has expired, checks against a
|
||||
// given expiration time.
|
||||
bool Expired(const DOMHighResTimeStamp aExpiry) const {
|
||||
return mTimestamp < aExpiry;
|
||||
}
|
||||
private:
|
||||
static const double constexpr EXPIRY_TIME_MILLISECONDS = 10 * 1000;
|
||||
uint32_t mCsrc;
|
||||
DOMHighResTimeStamp mTimestamp;
|
||||
};
|
||||
|
||||
// Gets the gathered contributing source stats for the last expiration period.
|
||||
// @param aId the stream id to use for populating inboundRtpStreamId field
|
||||
// @param aArr the array to append the stats objects to
|
||||
void
|
||||
GetContributingSourceStats(
|
||||
const nsString& aInboundStreamId,
|
||||
FallibleTArray<dom::RTCRTPContributingSourceStats>& aArr) const;
|
||||
|
||||
int32_t rtp_packets_sent() const { return rtp_packets_sent_; }
|
||||
int64_t rtp_bytes_sent() const { return rtp_bytes_sent_; }
|
||||
int32_t rtcp_packets_sent() const { return rtcp_packets_sent_; }
|
||||
|
@ -269,6 +311,9 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
int64_t rtp_bytes_sent_;
|
||||
int64_t rtp_bytes_received_;
|
||||
|
||||
// Only safe to access from STS thread.
|
||||
std::map<uint32_t, RtpCSRCStats> csrc_stats_;
|
||||
|
||||
// Written on Init. Read on STS thread.
|
||||
std::string pc_;
|
||||
std::string description_;
|
||||
|
@ -278,6 +323,8 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
nsAutoPtr<webrtc::RtpHeaderParser> rtp_parser_;
|
||||
|
||||
private:
|
||||
// Gets the current time as a DOMHighResTimeStamp
|
||||
static DOMHighResTimeStamp GetNow();
|
||||
nsresult Init_s();
|
||||
|
||||
bool IsRtp(const unsigned char *data, size_t len);
|
||||
|
|
|
@ -2090,6 +2090,7 @@ class RTCStatsReportInternalConstruct : public RTCStatsReportInternal {
|
|||
public:
|
||||
RTCStatsReportInternalConstruct(const nsString &pcid, DOMHighResTimeStamp now) {
|
||||
mPcid = pcid;
|
||||
mRtpContributingSourceStats.Construct();
|
||||
mInboundRTPStreamStats.Construct();
|
||||
mOutboundRTPStreamStats.Construct();
|
||||
mMediaStreamTrackStats.Construct();
|
||||
|
@ -3818,6 +3819,9 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) {
|
|||
}
|
||||
query->report->mInboundRTPStreamStats.Value().AppendElement(s,
|
||||
fallible);
|
||||
// Fill in Contributing Source statistics
|
||||
mp.GetContributingSourceStats(localId,
|
||||
query->report->mRtpContributingSourceStats.Value());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче