mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
Bug 906990 - Part 12: Report statistics from all components when the MediaStreamTrack is not specified. r=ekr
This commit is contained in:
parent
9d5486288c
commit
89a2b8ca6b
@ -119,13 +119,17 @@ GlobalPCList.prototype = {
|
||||
},
|
||||
|
||||
getStatsForEachPC: function(callback, errorCallback) {
|
||||
function getStatsFromPC(pcref) {
|
||||
if (pcref.get()) {
|
||||
pcref.get().getStatsInternal(null, callback, errorCallback);
|
||||
}
|
||||
}
|
||||
|
||||
for (let winId in this._list) {
|
||||
if (this._list.hasOwnProperty(winId)) {
|
||||
this.removeNullRefs(winId);
|
||||
if (this._list[winId]) {
|
||||
this._list[winId].forEach(function(pcref) {
|
||||
pcref.get().getStatsInternal(null, callback, errorCallback);
|
||||
});
|
||||
this._list[winId].forEach(getStatsFromPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +104,7 @@ enum RTCStatsIceCandidateType {
|
||||
};
|
||||
|
||||
dictionary RTCIceCandidateStats : RTCStats {
|
||||
DOMString componentId;
|
||||
DOMString candidateId;
|
||||
DOMString ipAddress;
|
||||
long portNumber;
|
||||
|
@ -1589,6 +1589,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
||||
pc.impl()->GetSTSThread(),
|
||||
stream->GetMediaStream()->GetStream(),
|
||||
pc_track_id,
|
||||
level,
|
||||
conduit, rtp_flow, rtcp_flow);
|
||||
|
||||
nsresult res = pipeline->Init();
|
||||
@ -1640,6 +1641,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
||||
pc.impl()->GetSTSThread(),
|
||||
stream->GetMediaStream()->GetStream(),
|
||||
pc_track_id,
|
||||
level,
|
||||
conduit, rtp_flow, rtcp_flow);
|
||||
|
||||
nsresult res = pipeline->Init();
|
||||
@ -2241,6 +2243,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
|
||||
pc.impl()->GetSTSThread(),
|
||||
stream->GetMediaStream(),
|
||||
pc_track_id,
|
||||
level,
|
||||
conduit, rtp_flow, rtcp_flow);
|
||||
|
||||
nsresult res = pipeline->Init();
|
||||
@ -2291,6 +2294,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
|
||||
pc.impl()->GetSTSThread(),
|
||||
stream->GetMediaStream(),
|
||||
pc_track_id,
|
||||
level,
|
||||
conduit, rtp_flow, rtcp_flow);
|
||||
|
||||
nsresult res = pipeline->Init();
|
||||
|
@ -71,12 +71,14 @@ class MediaPipeline : public sigslot::has_slots<> {
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
MediaStream *stream,
|
||||
TrackID track_id,
|
||||
int level,
|
||||
RefPtr<MediaSessionConduit> conduit,
|
||||
RefPtr<TransportFlow> rtp_transport,
|
||||
RefPtr<TransportFlow> rtcp_transport)
|
||||
: direction_(direction),
|
||||
stream_(stream),
|
||||
track_id_(track_id),
|
||||
level_(level),
|
||||
conduit_(conduit),
|
||||
rtp_transport_(rtp_transport),
|
||||
rtp_state_(MP_CONNECTING),
|
||||
@ -126,6 +128,7 @@ class MediaPipeline : public sigslot::has_slots<> {
|
||||
|
||||
virtual Direction direction() const { return direction_; }
|
||||
virtual TrackID trackid() const { return track_id_; }
|
||||
virtual int level() const { return level_; }
|
||||
|
||||
bool IsDoingRtcpMux() const {
|
||||
return (rtp_transport_ == rtcp_transport_);
|
||||
@ -194,6 +197,7 @@ class MediaPipeline : public sigslot::has_slots<> {
|
||||
// Used on STS and MediaStreamGraph threads.
|
||||
TrackID track_id_; // The track on the stream.
|
||||
// Written and used as the stream_;
|
||||
int level_; // The m-line index (starting at 1, to match convention)
|
||||
RefPtr<MediaSessionConduit> conduit_; // Our conduit. Written on the main
|
||||
// thread. Read on STS thread.
|
||||
|
||||
@ -315,12 +319,13 @@ class MediaPipelineTransmit : public MediaPipeline {
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
DOMMediaStream *domstream,
|
||||
TrackID track_id,
|
||||
int level,
|
||||
RefPtr<MediaSessionConduit> conduit,
|
||||
RefPtr<TransportFlow> rtp_transport,
|
||||
RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipeline(pc, TRANSMIT, main_thread, sts_thread,
|
||||
domstream->GetStream(), track_id, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
domstream->GetStream(), track_id, level,
|
||||
conduit, rtp_transport, rtcp_transport),
|
||||
listener_(new PipelineListener(conduit)),
|
||||
domstream_(domstream)
|
||||
{}
|
||||
@ -437,11 +442,12 @@ class MediaPipelineReceive : public MediaPipeline {
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
MediaStream *stream,
|
||||
TrackID track_id,
|
||||
int level,
|
||||
RefPtr<MediaSessionConduit> conduit,
|
||||
RefPtr<TransportFlow> rtp_transport,
|
||||
RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipeline(pc, RECEIVE, main_thread, sts_thread,
|
||||
stream, track_id, conduit, rtp_transport,
|
||||
stream, track_id, level, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
segments_added_(0) {
|
||||
}
|
||||
@ -464,11 +470,12 @@ class MediaPipelineReceiveAudio : public MediaPipelineReceive {
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
MediaStream *stream,
|
||||
TrackID track_id,
|
||||
int level,
|
||||
RefPtr<AudioSessionConduit> conduit,
|
||||
RefPtr<TransportFlow> rtp_transport,
|
||||
RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipelineReceive(pc, main_thread, sts_thread,
|
||||
stream, track_id, conduit, rtp_transport,
|
||||
stream, track_id, level, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
listener_(new PipelineListener(stream->AsSourceStream(),
|
||||
track_id, conduit)) {
|
||||
@ -526,11 +533,12 @@ class MediaPipelineReceiveVideo : public MediaPipelineReceive {
|
||||
nsCOMPtr<nsIEventTarget> sts_thread,
|
||||
MediaStream *stream,
|
||||
TrackID track_id,
|
||||
int level,
|
||||
RefPtr<VideoSessionConduit> conduit,
|
||||
RefPtr<TransportFlow> rtp_transport,
|
||||
RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipelineReceive(pc, main_thread, sts_thread,
|
||||
stream, track_id, conduit, rtp_transport,
|
||||
stream, track_id, level, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
renderer_(new PipelineRenderer(MOZ_THIS_IN_INITIALIZER_LIST())),
|
||||
listener_(new PipelineListener(stream->AsSourceStream(), track_id)) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cerrno>
|
||||
#include <deque>
|
||||
#include <sstream>
|
||||
|
||||
#include "base/histogram.h"
|
||||
#include "vcm.h"
|
||||
@ -32,6 +33,7 @@
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "prtime.h"
|
||||
|
||||
#include "runnable_utils.h"
|
||||
#include "PeerConnectionCtx.h"
|
||||
@ -56,6 +58,7 @@
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIDOMDataChannel.h"
|
||||
#include "nsIDOMLocation.h"
|
||||
#include "mozilla/dom/RTCConfigurationBinding.h"
|
||||
#include "mozilla/dom/RTCStatsReportBinding.h"
|
||||
#include "mozilla/dom/RTCPeerConnectionBinding.h"
|
||||
@ -709,8 +712,34 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
||||
MOZ_ASSERT(aWindow);
|
||||
mWindow = aWindow;
|
||||
NS_ENSURE_STATE(mWindow);
|
||||
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
|
||||
PRTime timestamp = PR_Now();
|
||||
// Ok if we truncate this.
|
||||
char temp[128];
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsIDOMLocation* location = nullptr;
|
||||
mWindow->GetLocation(&location);
|
||||
MOZ_ASSERT(location);
|
||||
nsString locationAStr;
|
||||
location->ToString(locationAStr);
|
||||
|
||||
nsCString locationCStr;
|
||||
CopyUTF16toUTF8(locationAStr, locationCStr);
|
||||
PR_snprintf(temp,
|
||||
sizeof(temp),
|
||||
"%ull (id=%u url=%s)",
|
||||
timestamp,
|
||||
mWindow->WindowID(),
|
||||
locationCStr.get());
|
||||
#else
|
||||
PR_snprintf(temp, sizeof(temp), "%ull", timestamp);
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
|
||||
mName = temp;
|
||||
|
||||
// Generate a random handle
|
||||
unsigned char handle_bin[8];
|
||||
SECStatus rv;
|
||||
@ -1259,29 +1288,49 @@ PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector, bool internalStats) {
|
||||
|
||||
// Gather up pipelines from mMedia and dispatch them to STS for inspection
|
||||
|
||||
nsAutoPtr<std::vector<RefPtr<MediaPipeline>>> pipelines(
|
||||
new std::vector<RefPtr<MediaPipeline>>());
|
||||
std::vector<RefPtr<MediaPipeline>> pipelines;
|
||||
TrackID trackId = aSelector ? aSelector->GetTrackID() : 0;
|
||||
|
||||
for (int i = 0, len = mMedia->LocalStreamsLength(); i < len; i++) {
|
||||
PushBackSelect(*pipelines, mMedia->GetLocalStream(i)->GetPipelines(), trackId);
|
||||
PushBackSelect(pipelines, mMedia->GetLocalStream(i)->GetPipelines(), trackId);
|
||||
}
|
||||
for (int i = 0, len = mMedia->RemoteStreamsLength(); i < len; i++) {
|
||||
PushBackSelect(*pipelines, mMedia->GetRemoteStream(i)->GetPipelines(), trackId);
|
||||
PushBackSelect(pipelines, mMedia->GetRemoteStream(i)->GetPipelines(), trackId);
|
||||
}
|
||||
|
||||
// From the list of MediaPipelines, determine the set of NrIceMediaStreams
|
||||
// we are interested in.
|
||||
std::vector<RefPtr<NrIceMediaStream> > streams;
|
||||
RefPtr<NrIceCtx> iceCtx(mMedia->ice_ctx());
|
||||
for (auto p = pipelines.begin(); p != pipelines.end(); ++p) {
|
||||
size_t level = p->get()->level();
|
||||
// TODO(bcampen@mozilla.com): I may need to revisit this for bundle.
|
||||
// (Bug 786234)
|
||||
RefPtr<NrIceMediaStream> temp(mMedia->ice_media_stream(level-1));
|
||||
if (temp.get()) {
|
||||
streams.push_back(temp);
|
||||
} else {
|
||||
CSFLogError(logTag, "Failed to get NrIceMediaStream for level %u "
|
||||
"in %s: %s",
|
||||
level, __FUNCTION__, mHandle.c_str());
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp now;
|
||||
nsresult rv = GetTimeSinceEpoch(&now);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mSTSThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::GetStats_s,
|
||||
trackId,
|
||||
internalStats,
|
||||
pipelines,
|
||||
now),
|
||||
WrapRunnableNM(&PeerConnectionImpl::GetStats_s,
|
||||
mHandle,
|
||||
mName,
|
||||
mThread,
|
||||
internalStats,
|
||||
pipelines,
|
||||
iceCtx,
|
||||
streams,
|
||||
now),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
return NS_OK;
|
||||
@ -1293,11 +1342,11 @@ PeerConnectionImpl::GetLogging(const nsAString& aPattern) {
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
std::string pattern(NS_ConvertUTF16toUTF8(aPattern).get());
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mSTSThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::GetLogging_s,
|
||||
pattern),
|
||||
WrapRunnableNM(&PeerConnectionImpl::GetLogging_s,
|
||||
mHandle,
|
||||
mThread,
|
||||
pattern),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
#endif
|
||||
@ -1737,6 +1786,13 @@ PeerConnectionImpl::GetHandle()
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
const std::string&
|
||||
PeerConnectionImpl::GetName()
|
||||
{
|
||||
PC_AUTO_ENTER_API_CALL_NO_CHECK();
|
||||
return mName;
|
||||
}
|
||||
|
||||
static mozilla::dom::PCImplIceConnectionState
|
||||
toDomIceConnectionState(NrIceCtx::ConnectionState state) {
|
||||
switch (state) {
|
||||
@ -1884,15 +1940,16 @@ PeerConnectionImpl::IceGatheringStateChange_m(PCImplIceGatheringState aState)
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsresult
|
||||
PeerConnectionImpl::GetStatsImpl_s(
|
||||
TrackID trackId,
|
||||
bool internalStats,
|
||||
nsAutoPtr<std::vector<RefPtr<MediaPipeline>>> pipelines,
|
||||
const std::vector<RefPtr<MediaPipeline>>& pipelines,
|
||||
const RefPtr<NrIceCtx>& iceCtx,
|
||||
const std::vector<RefPtr<NrIceMediaStream>>& streams,
|
||||
DOMHighResTimeStamp now,
|
||||
RTCStatsReportInternal *report) {
|
||||
RTCStatsReportInternal* report) {
|
||||
|
||||
// Gather stats from pipelines provided (can't touch mMedia + stream on STS)
|
||||
|
||||
for (auto it = pipelines->begin(); it != pipelines->end(); ++it) {
|
||||
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_");
|
||||
@ -1926,152 +1983,184 @@ PeerConnectionImpl::GetStatsImpl_s(
|
||||
}
|
||||
}
|
||||
|
||||
if (mMedia) {
|
||||
|
||||
// Gather stats from ICE
|
||||
|
||||
RefPtr<NrIceMediaStream> mediaStream(mMedia->ice_media_stream(trackId));
|
||||
if (mediaStream) {
|
||||
std::vector<NrIceCandidatePair> candPairs;
|
||||
mediaStream->GetCandidatePairs(&candPairs);
|
||||
NS_ConvertASCIItoUTF16 componentId(mediaStream->name().c_str());
|
||||
for (auto p = candPairs.begin(); p != candPairs.end(); ++p) {
|
||||
NS_ConvertASCIItoUTF16 codeword(p->codeword.c_str());
|
||||
NS_ConvertASCIItoUTF16 localCodeword(p->local.codeword.c_str());
|
||||
NS_ConvertASCIItoUTF16 remoteCodeword(p->remote.codeword.c_str());
|
||||
// Only expose candidate-pair statistics to chrome, until we've thought
|
||||
// through the implications of exposing it to content.
|
||||
|
||||
if (internalStats) {
|
||||
RTCIceCandidatePairStats s;
|
||||
s.mId.Construct(codeword);
|
||||
s.mComponentId.Construct(componentId);
|
||||
s.mTimestamp.Construct(now);
|
||||
s.mType.Construct(RTCStatsType::Candidatepair);
|
||||
|
||||
// Not quite right; we end up with duplicate candidates. Will fix.
|
||||
s.mLocalCandidateId.Construct(localCodeword);
|
||||
s.mRemoteCandidateId.Construct(remoteCodeword);
|
||||
s.mNominated.Construct(p->nominated);
|
||||
s.mMozPriority.Construct(p->priority);
|
||||
s.mSelected.Construct(p->selected);
|
||||
s.mState.Construct(RTCStatsIceCandidatePairState(p->state));
|
||||
report->mIceCandidatePairStats.Value().AppendElement(s);
|
||||
}
|
||||
|
||||
{
|
||||
RTCIceCandidateStats local;
|
||||
local.mId.Construct(localCodeword);
|
||||
local.mTimestamp.Construct(now);
|
||||
local.mType.Construct(RTCStatsType::Localcandidate);
|
||||
local.mCandidateType.Construct(
|
||||
RTCStatsIceCandidateType(p->local.type));
|
||||
local.mIpAddress.Construct(
|
||||
NS_ConvertASCIItoUTF16(p->local.cand_addr.host.c_str()));
|
||||
local.mPortNumber.Construct(p->local.cand_addr.port);
|
||||
report->mIceCandidateStats.Value().AppendElement(local);
|
||||
}
|
||||
|
||||
{
|
||||
RTCIceCandidateStats remote;
|
||||
remote.mId.Construct(remoteCodeword);
|
||||
remote.mTimestamp.Construct(now);
|
||||
remote.mType.Construct(RTCStatsType::Remotecandidate);
|
||||
remote.mCandidateType.Construct(
|
||||
RTCStatsIceCandidateType(p->remote.type));
|
||||
remote.mIpAddress.Construct(
|
||||
NS_ConvertASCIItoUTF16(p->remote.cand_addr.host.c_str()));
|
||||
remote.mPortNumber.Construct(p->remote.cand_addr.port);
|
||||
report->mIceCandidateStats.Value().AppendElement(remote);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Gather stats from ICE
|
||||
for (auto s = streams.begin(); s != streams.end(); ++s) {
|
||||
FillStatsReport_s(**s, internalStats, now, report);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::GetStats_s(
|
||||
TrackID trackId,
|
||||
void PeerConnectionImpl::FillStatsReport_s(
|
||||
NrIceMediaStream& mediaStream,
|
||||
bool internalStats,
|
||||
nsAutoPtr<std::vector<RefPtr<MediaPipeline>>> pipelines,
|
||||
DOMHighResTimeStamp now,
|
||||
RTCStatsReportInternal* report) {
|
||||
std::vector<NrIceCandidatePair> candPairs;
|
||||
nsresult res = mediaStream.GetCandidatePairs(&candPairs);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
CSFLogError(logTag, "%s: Error getting candidate pairs", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ConvertASCIItoUTF16 componentId(mediaStream.name().c_str());
|
||||
for (auto p = candPairs.begin(); p != candPairs.end(); ++p) {
|
||||
NS_ConvertASCIItoUTF16 codeword(p->codeword.c_str());
|
||||
NS_ConvertASCIItoUTF16 localCodeword(p->local.codeword.c_str());
|
||||
NS_ConvertASCIItoUTF16 remoteCodeword(p->remote.codeword.c_str());
|
||||
// Only expose candidate-pair statistics to chrome, until we've thought
|
||||
// through the implications of exposing it to content.
|
||||
|
||||
if (internalStats) {
|
||||
RTCIceCandidatePairStats s;
|
||||
s.mId.Construct(codeword);
|
||||
s.mComponentId.Construct(componentId);
|
||||
s.mTimestamp.Construct(now);
|
||||
s.mType.Construct(RTCStatsType::Candidatepair);
|
||||
|
||||
s.mLocalCandidateId.Construct(localCodeword);
|
||||
s.mRemoteCandidateId.Construct(remoteCodeword);
|
||||
s.mNominated.Construct(p->nominated);
|
||||
s.mMozPriority.Construct(p->priority);
|
||||
s.mSelected.Construct(p->selected);
|
||||
s.mState.Construct(RTCStatsIceCandidatePairState(p->state));
|
||||
report->mIceCandidatePairStats.Value().AppendElement(s);
|
||||
}
|
||||
|
||||
{
|
||||
RTCIceCandidateStats local;
|
||||
local.mComponentId.Construct(componentId);
|
||||
local.mId.Construct(localCodeword);
|
||||
local.mTimestamp.Construct(now);
|
||||
local.mType.Construct(RTCStatsType::Localcandidate);
|
||||
local.mCandidateType.Construct(
|
||||
RTCStatsIceCandidateType(p->local.type));
|
||||
local.mIpAddress.Construct(
|
||||
NS_ConvertASCIItoUTF16(p->local.cand_addr.host.c_str()));
|
||||
local.mPortNumber.Construct(p->local.cand_addr.port);
|
||||
report->mIceCandidateStats.Value().AppendElement(local);
|
||||
}
|
||||
|
||||
{
|
||||
RTCIceCandidateStats remote;
|
||||
remote.mComponentId.Construct(componentId);
|
||||
remote.mId.Construct(remoteCodeword);
|
||||
remote.mTimestamp.Construct(now);
|
||||
remote.mType.Construct(RTCStatsType::Remotecandidate);
|
||||
remote.mCandidateType.Construct(
|
||||
RTCStatsIceCandidateType(p->remote.type));
|
||||
remote.mIpAddress.Construct(
|
||||
NS_ConvertASCIItoUTF16(p->remote.cand_addr.host.c_str()));
|
||||
remote.mPortNumber.Construct(p->remote.cand_addr.port);
|
||||
report->mIceCandidateStats.Value().AppendElement(remote);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::GetStats_s(
|
||||
const std::string& pcHandle, // The Runnable holds the memory
|
||||
const std::string& pcName, // The Runnable holds the memory
|
||||
nsCOMPtr<nsIThread> callbackThread,
|
||||
bool internalStats,
|
||||
const std::vector<RefPtr<MediaPipeline>>& pipelines,
|
||||
const RefPtr<NrIceCtx>& iceCtx,
|
||||
const std::vector<RefPtr<NrIceMediaStream>>& streams,
|
||||
DOMHighResTimeStamp now) {
|
||||
|
||||
nsAutoPtr<RTCStatsReportInternal> report(new RTCStatsReportInternalConstruct(
|
||||
NS_ConvertASCIItoUTF16(mHandle.c_str()), now));
|
||||
// We do not use the pcHandle here, since that's risky to expose to content.
|
||||
nsAutoPtr<RTCStatsReportInternal> report(
|
||||
new RTCStatsReportInternalConstruct(
|
||||
NS_ConvertASCIItoUTF16(pcName.c_str()),
|
||||
now));
|
||||
|
||||
nsresult rv = report ? GetStatsImpl_s(trackId, internalStats, pipelines, now,
|
||||
report)
|
||||
: NS_ERROR_UNEXPECTED;
|
||||
nsresult rv = GetStatsImpl_s(internalStats,
|
||||
pipelines,
|
||||
iceCtx,
|
||||
streams,
|
||||
now,
|
||||
report);
|
||||
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::OnStatsReport_m,
|
||||
rv,
|
||||
pipelines, // return for release on main thread
|
||||
report),
|
||||
RUN_ON_THREAD(callbackThread,
|
||||
WrapRunnableNM(&PeerConnectionImpl::OnStatsReport_m,
|
||||
pcHandle,
|
||||
rv,
|
||||
pipelines, // return for release on main thread
|
||||
report),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::OnStatsReport_m(
|
||||
const std::string& pcHandle,
|
||||
nsresult result,
|
||||
nsAutoPtr<std::vector<RefPtr<MediaPipeline>>> pipelines, //returned for release
|
||||
const std::vector<RefPtr<MediaPipeline>>& pipelines, //returned for release
|
||||
nsAutoPtr<RTCStatsReportInternal> report) {
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (pco) {
|
||||
JSErrorResult rv;
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
pco->OnGetStatsSuccess(*report, rv);
|
||||
} else {
|
||||
pco->OnGetStatsError(kInternalError,
|
||||
ObString("Failed to fetch statistics"),
|
||||
rv);
|
||||
}
|
||||
|
||||
if (rv.Failed()) {
|
||||
CSFLogError(logTag, "Error firing stats observer callback");
|
||||
// Is the PeerConnectionImpl still around?
|
||||
PeerConnectionWrapper pcw(pcHandle);
|
||||
if (pcw.impl()) {
|
||||
nsRefPtr<PeerConnectionObserver> pco =
|
||||
do_QueryObjectReferent(pcw.impl()->mPCObserver);
|
||||
if (pco) {
|
||||
JSErrorResult rv;
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
pco->OnGetStatsSuccess(*report, rv);
|
||||
} else {
|
||||
pco->OnGetStatsError(kInternalError,
|
||||
ObString("Failed to fetch statistics"),
|
||||
rv);
|
||||
}
|
||||
|
||||
if (rv.Failed()) {
|
||||
CSFLogError(logTag, "Error firing stats observer callback");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::GetLogging_s(const std::string& pattern) {
|
||||
void PeerConnectionImpl::GetLogging_s(const std::string& pcHandle,
|
||||
nsCOMPtr<nsIThread> callbackThread,
|
||||
const std::string& pattern) {
|
||||
RLogRingBuffer* logs = RLogRingBuffer::GetInstance();
|
||||
std::deque<std::string> result;
|
||||
logs->Filter(pattern, 0, &result);
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::OnGetLogging_m,
|
||||
pattern,
|
||||
result),
|
||||
nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
|
||||
logs->Filter(pattern, 0, result);
|
||||
RUN_ON_THREAD(callbackThread,
|
||||
WrapRunnableNM(&PeerConnectionImpl::OnGetLogging_m,
|
||||
pcHandle,
|
||||
pattern,
|
||||
result),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::OnGetLogging_m(const std::string& pattern,
|
||||
const std::deque<std::string>& logging) {
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
void PeerConnectionImpl::OnGetLogging_m(
|
||||
const std::string& pcHandle,
|
||||
const std::string& pattern,
|
||||
nsAutoPtr<std::deque<std::string>> logging) {
|
||||
|
||||
JSErrorResult rv;
|
||||
if (!logging.empty()) {
|
||||
Sequence<nsString> nsLogs;
|
||||
for (auto l = logging.begin(); l != logging.end(); ++l) {
|
||||
nsLogs.AppendElement(ObString(l->c_str()));
|
||||
// Is the PeerConnectionImpl still around?
|
||||
PeerConnectionWrapper pcw(pcHandle);
|
||||
if (pcw.impl()) {
|
||||
nsRefPtr<PeerConnectionObserver> pco =
|
||||
do_QueryObjectReferent(pcw.impl()->mPCObserver);
|
||||
if (pco) {
|
||||
JSErrorResult rv;
|
||||
if (!logging->empty()) {
|
||||
Sequence<nsString> nsLogs;
|
||||
for (auto l = logging->begin(); l != logging->end(); ++l) {
|
||||
nsLogs.AppendElement(ObString(l->c_str()));
|
||||
}
|
||||
pco->OnGetLoggingSuccess(nsLogs, rv);
|
||||
} else {
|
||||
pco->OnGetLoggingError(kInternalError,
|
||||
ObString(("No logging matching pattern " + pattern).c_str()), rv);
|
||||
}
|
||||
|
||||
if (rv.Failed()) {
|
||||
CSFLogError(logTag, "Error firing stats observer callback");
|
||||
}
|
||||
}
|
||||
pco->OnGetLoggingSuccess(nsLogs, rv);
|
||||
} else {
|
||||
pco->OnGetLoggingError(kInternalError,
|
||||
ObString(("No logging matching pattern " + pattern).c_str()), rv);
|
||||
}
|
||||
|
||||
if (rv.Failed()) {
|
||||
CSFLogError(logTag, "Error firing stats observer callback");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
|
@ -223,6 +223,9 @@ public:
|
||||
// Handle system to allow weak references to be passed through C code
|
||||
virtual const std::string& GetHandle();
|
||||
|
||||
// Name suitable for exposing to content
|
||||
virtual const std::string& GetName();
|
||||
|
||||
// ICE events
|
||||
void IceConnectionStateChange(NrIceCtx* ctx,
|
||||
NrIceCtx::ConnectionState state);
|
||||
@ -540,32 +543,51 @@ private:
|
||||
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// TODO(bcampen@mozilla.com): Once the dust settles on this stuff, it
|
||||
// probably makes sense to make these static in PeerConnectionImpl.cpp
|
||||
// (ie; stop exporting them)
|
||||
|
||||
// Fills in an RTCStatsReportInternal. Must be run on STS.
|
||||
void GetStats_s(
|
||||
mozilla::TrackID trackId,
|
||||
static void GetStats_s(
|
||||
const std::string& pcHandle,
|
||||
const std::string& pcName,
|
||||
nsCOMPtr<nsIThread> callbackThread,
|
||||
bool internalStats,
|
||||
nsAutoPtr<std::vector<mozilla::RefPtr<mozilla::MediaPipeline>>> pipelines,
|
||||
const std::vector<mozilla::RefPtr<mozilla::MediaPipeline>> &pipelines,
|
||||
const mozilla::RefPtr<NrIceCtx> &iceCtx,
|
||||
const std::vector<mozilla::RefPtr<NrIceMediaStream>> &streams,
|
||||
DOMHighResTimeStamp now);
|
||||
|
||||
nsresult GetStatsImpl_s(
|
||||
mozilla::TrackID trackId,
|
||||
static nsresult GetStatsImpl_s(
|
||||
bool internalStats,
|
||||
nsAutoPtr<std::vector<mozilla::RefPtr<mozilla::MediaPipeline>>> pipelines,
|
||||
const std::vector<mozilla::RefPtr<mozilla::MediaPipeline>> &pipelines,
|
||||
const mozilla::RefPtr<NrIceCtx> &iceCtx,
|
||||
const std::vector<mozilla::RefPtr<NrIceMediaStream>> &streams,
|
||||
DOMHighResTimeStamp now,
|
||||
mozilla::dom::RTCStatsReportInternal *report);
|
||||
|
||||
static void FillStatsReport_s(
|
||||
NrIceMediaStream& stream,
|
||||
bool internalStats,
|
||||
DOMHighResTimeStamp now,
|
||||
mozilla::dom::RTCStatsReportInternal* stats);
|
||||
|
||||
// Sends an RTCStatsReport to JS. Must run on main thread.
|
||||
void OnStatsReport_m(
|
||||
static void OnStatsReport_m(
|
||||
const std::string& pcHandle,
|
||||
nsresult result,
|
||||
nsAutoPtr<std::vector<mozilla::RefPtr<mozilla::MediaPipeline>>> pipelines,
|
||||
const 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);
|
||||
static void GetLogging_s(const std::string& pcHandle,
|
||||
nsCOMPtr<nsIThread> callbackThread,
|
||||
const std::string& pattern);
|
||||
|
||||
// Sends logging to JS. Must run on main thread.
|
||||
void OnGetLogging_m(const std::string& pattern,
|
||||
const std::deque<std::string>& logging);
|
||||
static void OnGetLogging_m(const std::string& pcHandle,
|
||||
const std::string& pattern,
|
||||
nsAutoPtr<std::deque<std::string>> logging);
|
||||
#endif
|
||||
|
||||
// Timecard used to measure processing time. This should be the first class
|
||||
@ -605,6 +627,9 @@ private:
|
||||
// A handle to refer to this PC with
|
||||
std::string mHandle;
|
||||
|
||||
// A name for this PC that we are willing to expose to content.
|
||||
std::string mName;
|
||||
|
||||
// The target to run stuff on
|
||||
nsCOMPtr<nsIEventTarget> mSTSThread;
|
||||
|
||||
|
@ -148,7 +148,7 @@ nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_serv
|
||||
{
|
||||
// TODO(ekr@rtfm.com): need some way to set not offerer later
|
||||
// Looks like a bug in the NrIceCtx API.
|
||||
mIceCtx = NrIceCtx::Create("PC:" + mParent->GetHandle(), true);
|
||||
mIceCtx = NrIceCtx::Create("PC:" + mParent->GetName(), true);
|
||||
if(!mIceCtx) {
|
||||
CSFLogError(logTag, "%s: Failed to create Ice Context", __FUNCTION__);
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -191,11 +191,11 @@ nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_serv
|
||||
// One each for audio, video and DataChannel
|
||||
// TODO: this will be re-visited
|
||||
RefPtr<NrIceMediaStream> audioStream =
|
||||
mIceCtx->CreateStream((mParent->GetHandle()+"/stream1/audio").c_str(), 2);
|
||||
mIceCtx->CreateStream((mParent->GetName()+": stream1/audio").c_str(), 2);
|
||||
RefPtr<NrIceMediaStream> videoStream =
|
||||
mIceCtx->CreateStream((mParent->GetHandle()+"/stream2/video").c_str(), 2);
|
||||
mIceCtx->CreateStream((mParent->GetName()+": stream2/video").c_str(), 2);
|
||||
RefPtr<NrIceMediaStream> dcStream =
|
||||
mIceCtx->CreateStream((mParent->GetHandle()+"/stream3/data").c_str(), 2);
|
||||
mIceCtx->CreateStream((mParent->GetName()+": stream3/data").c_str(), 2);
|
||||
|
||||
if (!audioStream) {
|
||||
CSFLogError(logTag, "%s: audio stream is NULL", __FUNCTION__);
|
||||
|
@ -197,6 +197,7 @@ class TestAgentSend : public TestAgent {
|
||||
test_utils->sts_target(),
|
||||
audio_,
|
||||
1,
|
||||
1,
|
||||
audio_conduit_,
|
||||
audio_rtp_transport_.flow_,
|
||||
audio_rtcp_transport_.flow_);
|
||||
@ -246,7 +247,7 @@ class TestAgentReceive : public TestAgent {
|
||||
test_pc,
|
||||
nullptr,
|
||||
test_utils->sts_target(),
|
||||
audio_->GetStream(), 1,
|
||||
audio_->GetStream(), 1, 1,
|
||||
static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get()),
|
||||
audio_rtp_transport_.flow_, audio_rtcp_transport_.flow_);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user