mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
Bug 908695 - Collect pipelines on main, dispatch to STS for stats. r=jesup
This commit is contained in:
parent
98d5e0c51a
commit
47521f776e
@ -50,6 +50,7 @@ namespace mozilla {
|
||||
static char kDTLSExporterLabel[] = "EXTRACTOR-dtls_srtp";
|
||||
|
||||
MediaPipeline::~MediaPipeline() {
|
||||
ASSERT_ON_THREAD(main_thread_);
|
||||
MOZ_ASSERT(!stream_); // Check that we have shut down already.
|
||||
MOZ_MTLOG(ML_INFO, "Destroying MediaPipeline: " << description_);
|
||||
}
|
||||
|
@ -1191,24 +1191,68 @@ PeerConnectionImpl::GetTimeSinceEpoch(DOMHighResTimeStamp *result) {
|
||||
*result = perf->Now() + perf->Timing()->NavigationStart();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class RTCStatsReportInternalConstruct : public RTCStatsReportInternal {
|
||||
public:
|
||||
RTCStatsReportInternalConstruct(const nsString &pcid, DOMHighResTimeStamp now) {
|
||||
mPcid = pcid;
|
||||
mInboundRTPStreamStats.Construct();
|
||||
mOutboundRTPStreamStats.Construct();
|
||||
mMediaStreamTrackStats.Construct();
|
||||
mMediaStreamStats.Construct();
|
||||
mTransportStats.Construct();
|
||||
mIceComponentStats.Construct();
|
||||
mIceCandidatePairStats.Construct();
|
||||
mIceCandidateStats.Construct();
|
||||
mCodecStats.Construct();
|
||||
}
|
||||
};
|
||||
|
||||
// Specialized helper - push map[key] if specified or all map values onto array
|
||||
|
||||
static void
|
||||
PushBackSelect(std::vector<RefPtr<MediaPipeline>>& aDst,
|
||||
const std::map<TrackID, RefPtr<mozilla::MediaPipeline>> & aSrc,
|
||||
TrackID aKey = 0) {
|
||||
auto begin = aKey ? aSrc.find(aKey) : aSrc.begin(), it = begin;
|
||||
for (auto end = (aKey && begin != aSrc.end())? ++begin : aSrc.end();
|
||||
it != end; ++it) {
|
||||
aDst.push_back(it->second);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector,
|
||||
bool internalStats) {
|
||||
PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector, bool internalStats) {
|
||||
PC_AUTO_ENTER_API_CALL(true);
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
uint32_t track = aSelector ? aSelector->GetTrackID() : 0;
|
||||
MOZ_ASSERT(mMedia);
|
||||
|
||||
// Gather up pipelines from mMedia and dispatch them to STS for inspection
|
||||
|
||||
nsAutoPtr<std::vector<RefPtr<MediaPipeline>>> pipelines(
|
||||
new std::vector<RefPtr<MediaPipeline>>());
|
||||
TrackID trackId = aSelector ? aSelector->GetTrackID() : 0;
|
||||
|
||||
for (int i = 0, len = mMedia->LocalStreamsLength(); i < len; i++) {
|
||||
PushBackSelect(*pipelines, mMedia->GetLocalStream(i)->GetPipelines(), trackId);
|
||||
}
|
||||
for (int i = 0, len = mMedia->RemoteStreamsLength(); i < len; i++) {
|
||||
PushBackSelect(*pipelines, mMedia->GetRemoteStream(i)->GetPipelines(), trackId);
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp now;
|
||||
nsresult rv = GetTimeSinceEpoch(&now);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mSTSThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::GetStats_s,
|
||||
track,
|
||||
trackId,
|
||||
internalStats,
|
||||
pipelines,
|
||||
now),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
@ -1798,44 +1842,51 @@ PeerConnectionImpl::IceGatheringStateChange_m(PCImplIceGatheringState aState)
|
||||
}
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
class RTCStatsReportInternalConstruct : public RTCStatsReportInternal {
|
||||
public:
|
||||
RTCStatsReportInternalConstruct(const nsString &pcid, DOMHighResTimeStamp now) {
|
||||
mPcid = pcid;
|
||||
mInboundRTPStreamStats.Construct();
|
||||
mOutboundRTPStreamStats.Construct();
|
||||
mMediaStreamTrackStats.Construct();
|
||||
mMediaStreamStats.Construct();
|
||||
mTransportStats.Construct();
|
||||
mIceComponentStats.Construct();
|
||||
mIceCandidatePairStats.Construct();
|
||||
mIceCandidateStats.Construct();
|
||||
mCodecStats.Construct();
|
||||
}
|
||||
};
|
||||
|
||||
nsresult PeerConnectionImpl::GetStatsImpl_s(
|
||||
nsresult
|
||||
PeerConnectionImpl::GetStatsImpl_s(
|
||||
TrackID trackId,
|
||||
bool internalStats,
|
||||
nsAutoPtr<std::vector<RefPtr<MediaPipeline>>> pipelines,
|
||||
DOMHighResTimeStamp now,
|
||||
RTCStatsReportInternal *report) {
|
||||
|
||||
// Gather stats from pipelines provided (can't touch mMedia + stream on STS)
|
||||
|
||||
for (auto it = pipelines->begin(); it != pipelines->end(); ++it) {
|
||||
const MediaPipeline& mp = **it;
|
||||
nsString idstr = (mp.Conduit()->type() == MediaSessionConduit::AUDIO) ?
|
||||
NS_LITERAL_STRING("audio_") : NS_LITERAL_STRING("video_");
|
||||
idstr.AppendInt(mp.trackid());
|
||||
|
||||
switch (mp.direction()) {
|
||||
case MediaPipeline::TRANSMIT: {
|
||||
RTCOutboundRTPStreamStats s;
|
||||
s.mTimestamp.Construct(now);
|
||||
s.mId.Construct(NS_LITERAL_STRING("outbound_rtp_") + idstr);
|
||||
s.mType.Construct(RTCStatsType::Outboundrtp);
|
||||
// TODO: Get SSRC
|
||||
// int channel = mp.Conduit()->GetChannel();
|
||||
s.mSsrc.Construct(NS_LITERAL_STRING("123457"));
|
||||
s.mPacketsSent.Construct(mp.rtp_packets_sent());
|
||||
s.mBytesSent.Construct(mp.rtp_bytes_sent());
|
||||
report->mOutboundRTPStreamStats.Value().AppendElement(s);
|
||||
break;
|
||||
}
|
||||
case MediaPipeline::RECEIVE: {
|
||||
RTCInboundRTPStreamStats s;
|
||||
s.mTimestamp.Construct(now);
|
||||
s.mId.Construct(NS_LITERAL_STRING("inbound_rtp_") + idstr);
|
||||
s.mType.Construct(RTCStatsType::Inboundrtp);
|
||||
s.mSsrc.Construct(NS_LITERAL_STRING("123457"));
|
||||
s.mPacketsReceived.Construct(mp.rtp_packets_received());
|
||||
s.mBytesReceived.Construct(mp.rtp_bytes_received());
|
||||
report->mInboundRTPStreamStats.Value().AppendElement(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mMedia) {
|
||||
nsresult rv;
|
||||
|
||||
// Gather stats from media pipeline (can't touch stream itself on STS)
|
||||
|
||||
for (int i = 0, len = mMedia->LocalStreamsLength(); i < len; i++) {
|
||||
rv = mMedia->GetLocalStream(i)->GetPipelineStats(now, trackId,
|
||||
&report->mInboundRTPStreamStats.Value(),
|
||||
&report->mOutboundRTPStreamStats.Value());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
for (int i = 0, len = mMedia->RemoteStreamsLength(); i < len; i++) {
|
||||
rv = mMedia->GetRemoteStream(i)->GetPipelineStats(now, trackId,
|
||||
&report->mInboundRTPStreamStats.Value(),
|
||||
&report->mOutboundRTPStreamStats.Value());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Gather stats from ICE
|
||||
|
||||
@ -1902,27 +1953,29 @@ nsresult PeerConnectionImpl::GetStatsImpl_s(
|
||||
void PeerConnectionImpl::GetStats_s(
|
||||
TrackID trackId,
|
||||
bool internalStats,
|
||||
nsAutoPtr<std::vector<RefPtr<MediaPipeline>>> pipelines,
|
||||
DOMHighResTimeStamp now) {
|
||||
|
||||
nsAutoPtr<RTCStatsReportInternal> report(new RTCStatsReportInternalConstruct(
|
||||
NS_ConvertASCIItoUTF16(mHandle.c_str()), now));
|
||||
|
||||
nsresult rv = report ? GetStatsImpl_s(trackId, internalStats, now, report)
|
||||
nsresult rv = report ? GetStatsImpl_s(trackId, internalStats, pipelines, now,
|
||||
report)
|
||||
: NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::OnStatsReport_m,
|
||||
trackId,
|
||||
rv,
|
||||
pipelines, // return for release on main thread
|
||||
report),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::OnStatsReport_m(
|
||||
TrackID trackId,
|
||||
nsresult result,
|
||||
nsAutoPtr<std::vector<RefPtr<MediaPipeline>>> pipelines, //returned for release
|
||||
nsAutoPtr<RTCStatsReportInternal> report) {
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (pco) {
|
||||
|
@ -55,6 +55,7 @@ class NrIceCtx;
|
||||
class NrIceMediaStream;
|
||||
class NrIceStunServer;
|
||||
class NrIceTurnServer;
|
||||
class MediaPipeline;
|
||||
|
||||
#ifdef USE_FAKE_MEDIA_STREAMS
|
||||
typedef Fake_DOMMediaStream DOMMediaStream;
|
||||
@ -529,19 +530,24 @@ private:
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// Fills in an RTCStatsReportInternal. Must be run on STS.
|
||||
void GetStats_s(mozilla::TrackID trackId,
|
||||
bool internalStats,
|
||||
DOMHighResTimeStamp now);
|
||||
void GetStats_s(
|
||||
mozilla::TrackID trackId,
|
||||
bool internalStats,
|
||||
nsAutoPtr<std::vector<mozilla::RefPtr<mozilla::MediaPipeline>>> pipelines,
|
||||
DOMHighResTimeStamp now);
|
||||
|
||||
nsresult GetStatsImpl_s(mozilla::TrackID trackId,
|
||||
bool internalStats,
|
||||
DOMHighResTimeStamp now,
|
||||
mozilla::dom::RTCStatsReportInternal *report);
|
||||
nsresult GetStatsImpl_s(
|
||||
mozilla::TrackID trackId,
|
||||
bool internalStats,
|
||||
nsAutoPtr<std::vector<mozilla::RefPtr<mozilla::MediaPipeline>>> pipelines,
|
||||
DOMHighResTimeStamp now,
|
||||
mozilla::dom::RTCStatsReportInternal *report);
|
||||
|
||||
// Sends an RTCStatsReport to JS. Must run on main thread.
|
||||
void OnStatsReport_m(mozilla::TrackID trackId,
|
||||
nsresult result,
|
||||
nsAutoPtr<mozilla::dom::RTCStatsReportInternal> report);
|
||||
void OnStatsReport_m(
|
||||
nsresult result,
|
||||
nsAutoPtr<std::vector<mozilla::RefPtr<mozilla::MediaPipeline>>> pipelines,
|
||||
nsAutoPtr<mozilla::dom::RTCStatsReportInternal> report);
|
||||
|
||||
// Fetches logs matching pattern from RLogRingBuffer. Must be run on STS.
|
||||
void GetLogging_s(const std::string& pattern);
|
||||
|
@ -452,73 +452,6 @@ PeerConnectionMedia::IceStreamReady(NrIceMediaStream *aStream)
|
||||
CSFLogDebug(logTag, "%s: %s", __FUNCTION__, aStream->name().c_str());
|
||||
}
|
||||
|
||||
// This method exists for the unittests.
|
||||
// It allows visibility into the pipelines and flows.
|
||||
// It returns nullptr if no pipeline exists for this track number.
|
||||
mozilla::RefPtr<mozilla::MediaPipeline>
|
||||
SourceStreamInfo::GetPipeline(int aTrack) {
|
||||
std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
|
||||
mPipelines.find(aTrack);
|
||||
|
||||
if (it == mPipelines.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// This methods gathers statistics for the getStats API.
|
||||
// aTrack == 0 means gather stats for all tracks.
|
||||
|
||||
nsresult
|
||||
SourceStreamInfo::GetPipelineStats(DOMHighResTimeStamp now, int aTrack,
|
||||
Sequence<RTCInboundRTPStreamStats > *inbound,
|
||||
Sequence<RTCOutboundRTPStreamStats > *outbound)
|
||||
{
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
ASSERT_ON_THREAD(mParent->GetSTSThread());
|
||||
// walk through all the MediaPipelines and gather stats
|
||||
for (std::map<int, RefPtr<MediaPipeline> >::iterator it = mPipelines.begin();
|
||||
it != mPipelines.end();
|
||||
++it) {
|
||||
if (!aTrack || aTrack == it->first) {
|
||||
const MediaPipeline &mp = *it->second;
|
||||
nsString idstr = (mp.Conduit()->type() == MediaSessionConduit::AUDIO) ?
|
||||
NS_LITERAL_STRING("audio_") : NS_LITERAL_STRING("video_");
|
||||
idstr.AppendInt(mp.trackid());
|
||||
|
||||
switch (mp.direction()) {
|
||||
case MediaPipeline::TRANSMIT: {
|
||||
RTCOutboundRTPStreamStats s;
|
||||
s.mTimestamp.Construct(now);
|
||||
s.mId.Construct(NS_LITERAL_STRING("outbound_rtp_") + idstr);
|
||||
s.mType.Construct(RTCStatsType::Outboundrtp);
|
||||
// TODO: Get SSRC
|
||||
// int channel = mp.Conduit()->GetChannel();
|
||||
s.mSsrc.Construct(NS_LITERAL_STRING("123457"));
|
||||
s.mPacketsSent.Construct(mp.rtp_packets_sent());
|
||||
s.mBytesSent.Construct(mp.rtp_bytes_sent());
|
||||
outbound->AppendElement(s);
|
||||
break;
|
||||
}
|
||||
case MediaPipeline::RECEIVE: {
|
||||
RTCInboundRTPStreamStats s;
|
||||
s.mTimestamp.Construct(now);
|
||||
s.mId.Construct(NS_LITERAL_STRING("inbound_rtp_") + idstr);
|
||||
s.mType.Construct(RTCStatsType::Inboundrtp);
|
||||
s.mSsrc.Construct(NS_LITERAL_STRING("123457"));
|
||||
s.mPacketsReceived.Construct(mp.rtp_packets_received());
|
||||
s.mBytesReceived.Construct(mp.rtp_bytes_received());
|
||||
inbound->AppendElement(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
LocalSourceStreamInfo::StorePipeline(int aTrack,
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> aPipeline)
|
||||
|
@ -184,12 +184,13 @@ public:
|
||||
MOZ_ASSERT(mMediaStream);
|
||||
}
|
||||
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> GetPipeline(int aTrack);
|
||||
nsresult GetPipelineStats(DOMHighResTimeStamp now, int aTrack,
|
||||
mozilla::dom::Sequence<mozilla::dom::RTCInboundRTPStreamStats > *inbound,
|
||||
mozilla::dom::Sequence<mozilla::dom::RTCOutboundRTPStreamStats > *outbound);
|
||||
// This method exists for stats and the unittests.
|
||||
// It allows visibility into the pipelines and flows.
|
||||
const std::map<mozilla::TrackID, mozilla::RefPtr<mozilla::MediaPipeline>>&
|
||||
GetPipelines() const { return mPipelines; }
|
||||
|
||||
protected:
|
||||
std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> > mPipelines;
|
||||
std::map<mozilla::TrackID, mozilla::RefPtr<mozilla::MediaPipeline>> mPipelines;
|
||||
nsRefPtr<DOMMediaStream> mMediaStream;
|
||||
PeerConnectionMedia *mParent;
|
||||
};
|
||||
|
@ -1124,7 +1124,9 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return streamInfo->GetPipeline(track);
|
||||
const auto &pipelines = streamInfo->GetPipelines();
|
||||
auto it = pipelines.find(track);
|
||||
return (it == pipelines.end())? nullptr : it->second;
|
||||
}
|
||||
|
||||
void CheckMediaPipeline(int stream, int track, uint32_t flags,
|
||||
|
Loading…
Reference in New Issue
Block a user