Bug 908695 - Collect pipelines on main, dispatch to STS for stats. r=jesup

This commit is contained in:
Jan-Ivar Bruaroey 2013-12-11 23:42:12 -05:00
parent 98d5e0c51a
commit 47521f776e
6 changed files with 119 additions and 123 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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