--- a/dom/media/tests/mochitest/test_peerConnection_stats.html
+++ b/dom/media/tests/mochitest/test_peerConnection_stats.html
@@ -11,18 +11,18 @@
title: "webRtc Stats composition and sanity"
});
var statsExpectedByType = {
"inbound-rtp": {
expected: ["id", "timestamp", "type", "ssrc", "isRemote", "mediaType",
"packetsReceived", "packetsLost", "bytesReceived", "jitter",],
optional: ["roundTripTime", "remoteId", "nackCount",],
localVideoOnly: ["discardedPackets", "framerateStdDev", "framerateMean",
- "bitrateMean", "bitrateStdDev", "firCount", "pliCount",],
- unimplemented: ["mediaTrackId", "transportId", "codecId", "framesDecoded",
+ "bitrateMean", "bitrateStdDev", "firCount", "pliCount", "framesDecoded",],
+ unimplemented: ["mediaTrackId", "transportId", "codecId",
"packetsDiscarded", "associateStatsId",
"sliCount", "qpSum", "packetsRepaired", "fractionLost",
"burstPacketsLost", "burstLossCount", "burstDiscardCount",
"gapDiscardRate", "gapLossRate",],
deprecated: ["mozRtt"],
},
"outbound-rtp": {
expected: ["id", "timestamp", "type", "ssrc", "isRemote", "mediaType",
@@ -253,17 +253,20 @@ var pedanticChecks = report => {
expectations.localVideoOnly.forEach(field => {
ok(stat.inner[field] !== undefined, stat.type + " has field " + field
+ " when mediaType is video");
});
// discardedPackets
ok(stat.discardedPackets < 100, stat.type
+ ".discardedPackets is a sane number for a short test. value="
+ stat.discardedPackets);
-
+ // framesDecoded
+ ok(stat.framesDecoded > 0 && stat.framesDecoded < 1000000, stat.type
+ + ".framesDecoded is a sane number for a short test. value="
+ + stat.framesDecoded);
// bitrateMean
// special exception, TODO: Bug 1341533
if (stat.bitrateMean !== undefined) {
// TODO: uncomment when Bug 1341533 lands
// ok(stat.bitrateMean >= 0 && stat.bitrateMean < 2 ** 25,
// stat.type + ".bitrateMean is sane. value="
// + stat.bitrateMean);
}
--- a/dom/media/webrtc/WebrtcGlobal.h
+++ b/dom/media/webrtc/WebrtcGlobal.h
@@ -348,30 +348,32 @@ template<>
struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats>
{
typedef mozilla::dom::RTCInboundRTPStreamStats paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mBytesReceived);
WriteParam(aMsg, aParam.mDiscardedPackets);
+ WriteParam(aMsg, aParam.mFramesDecoded);
WriteParam(aMsg, aParam.mJitter);
WriteParam(aMsg, aParam.mMozAvSyncDelay);
WriteParam(aMsg, aParam.mMozJitterBufferDelay);
WriteParam(aMsg, aParam.mRoundTripTime);
WriteParam(aMsg, aParam.mPacketsLost);
WriteParam(aMsg, aParam.mPacketsReceived);
WriteRTCRTPStreamStats(aMsg, aParam);
WriteRTCStats(aMsg, aParam);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
!ReadParam(aMsg, aIter, &(aResult->mDiscardedPackets)) ||
+ !ReadParam(aMsg, aIter, &(aResult->mFramesDecoded)) ||
!ReadParam(aMsg, aIter, &(aResult->mJitter)) ||
!ReadParam(aMsg, aIter, &(aResult->mMozAvSyncDelay)) ||
!ReadParam(aMsg, aIter, &(aResult->mMozJitterBufferDelay)) ||
!ReadParam(aMsg, aIter, &(aResult->mRoundTripTime)) ||
!ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) ||
!ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) ||
!ReadRTCRTPStreamStats(aMsg, aIter, aResult) ||
!ReadRTCStats(aMsg, aIter, aResult)) {
--- a/dom/webidl/RTCStatsReport.webidl
+++ b/dom/webidl/RTCStatsReport.webidl
@@ -54,16 +54,17 @@ dictionary RTCInboundRTPStreamStats : RT
double jitter;
unsigned long packetsLost;
long mozAvSyncDelay;
long mozJitterBufferDelay;
long roundTripTime;
// Video decoder measurement, not present in RTCP case
unsigned long discardedPackets;
+ unsigned long framesDecoded;
};
dictionary RTCOutboundRTPStreamStats : RTCRTPStreamStats {
unsigned long packetsSent;
unsigned long long bytesSent;
double targetBitrate; // config encoder bitrate target of this SSRC in bits/s
// Video encoder measurements, not present in RTCP case
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.h
@@ -217,17 +217,18 @@ public:
uint32_t* framesEncoded) override
{
return false;
}
bool GetVideoDecoderStats(double* framerateMean,
double* framerateStdDev,
double* bitrateMean,
double* bitrateStdDev,
- uint32_t* discardedPackets) override
+ uint32_t* discardedPackets,
+ uint32_t* framesDecoded) override
{
return false;
}
bool GetAVStats(int32_t* jitterBufferDelayMs,
int32_t* playoutBufferDelayMs,
int32_t* avSyncOffsetMs) override;
bool GetRTPStats(unsigned int* jitterMs, unsigned int* cumulativeLost) override;
bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
--- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
+++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
@@ -273,17 +273,18 @@ public:
double* bitrateMean,
double* bitrateStdDev,
uint32_t* droppedFrames,
uint32_t* framesEncoded) = 0;
virtual bool GetVideoDecoderStats(double* framerateMean,
double* framerateStdDev,
double* bitrateMean,
double* bitrateStdDev,
- uint32_t* discardedPackets) = 0;
+ uint32_t* discardedPackets,
+ uint32_t* framesDecoded) = 0;
virtual bool GetAVStats(int32_t* jitterBufferDelayMs,
int32_t* playoutBufferDelayMs,
int32_t* avSyncOffsetMs) = 0;
virtual bool GetRTPStats(unsigned int* jitterMs,
unsigned int* cumulativeLost) = 0;
virtual bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
uint32_t* jitterMs,
uint32_t* packetsReceived,
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -146,24 +146,24 @@ WebrtcVideoConduit::StreamStatistics::Ge
if (mFrameRate.NumDataValues() && mBitrate.NumDataValues()) {
aOutFrMean = mFrameRate.Mean();
aOutFrStdDev = mFrameRate.StandardDeviation();
aOutBrMean = mBitrate.Mean();
aOutBrStdDev = mBitrate.StandardDeviation();
return true;
}
return false;
-};
+}
void
WebrtcVideoConduit::SendStreamStatistics::DroppedFrames(
uint32_t& aOutDroppedFrames) const
{
aOutDroppedFrames = mDroppedFrames;
-};
+}
void
WebrtcVideoConduit::SendStreamStatistics::Update(
const webrtc::VideoSendStream::Stats& aStats)
{
StreamStatistics::Update(aStats.encode_frame_rate, aStats.media_bitrate_bps);
if (!aStats.substreams.empty()) {
const webrtc::FrameCounts& fc =
@@ -173,33 +173,42 @@ WebrtcVideoConduit::SendStreamStatistics
"%s: framerate: %u, bitrate: %u, dropped frames delta: %u",
__FUNCTION__, aStats.encode_frame_rate,
aStats.media_bitrate_bps,
mFramesDeliveredToEncoder - mFramesEncoded - mDroppedFrames);
mDroppedFrames = mFramesDeliveredToEncoder - mFramesEncoded;
} else {
CSFLogVerbose(logTag, "%s stats.substreams is empty", __FUNCTION__);
}
-};
+}
void
WebrtcVideoConduit::ReceiveStreamStatistics::DiscardedPackets(
uint32_t& aOutDiscPackets) const
{
aOutDiscPackets = mDiscardedPackets;
-};
+}
+
+void
+WebrtcVideoConduit::ReceiveStreamStatistics::FramesDecoded(
+ uint32_t& aFramesDecoded) const
+{
+ aFramesDecoded = mFramesDecoded;
+}
void
WebrtcVideoConduit::ReceiveStreamStatistics::Update(
const webrtc::VideoReceiveStream::Stats& aStats)
{
CSFLogVerbose(logTag, "%s ", __FUNCTION__);
StreamStatistics::Update(aStats.decode_frame_rate, aStats.total_bitrate_bps);
mDiscardedPackets = aStats.discarded_packets;
-};
+ mFramesDecoded = aStats.frame_counts.key_frames
+ + aStats.frame_counts.delta_frames;
+}
/**
* Factory Method for VideoConduit
*/
RefPtr<VideoSessionConduit>
VideoSessionConduit::Create(RefPtr<WebRtcCallWrapper> aCall)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
@@ -923,26 +932,28 @@ WebrtcVideoConduit::GetVideoEncoderStats
}
}
bool
WebrtcVideoConduit::GetVideoDecoderStats(double* framerateMean,
double* framerateStdDev,
double* bitrateMean,
double* bitrateStdDev,
- uint32_t* discardedPackets)
+ uint32_t* discardedPackets,
+ uint32_t* framesDecoded)
{
{
MutexAutoLock lock(mCodecMutex);
if (!mEngineReceiving || !mRecvStream) {
return false;
}
mRecvStreamStats.GetVideoStreamStats(*framerateMean, *framerateStdDev,
*bitrateMean, *bitrateStdDev);
mRecvStreamStats.DiscardedPackets(*discardedPackets);
+ mRecvStreamStats.FramesDecoded(*framesDecoded);
return true;
}
}
bool
WebrtcVideoConduit::GetAVStats(int32_t* jitterBufferDelayMs,
int32_t* playoutBufferDelayMs,
int32_t* avSyncOffsetMs)
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -317,17 +317,18 @@ public:
double* bitrateMean,
double* bitrateStdDev,
uint32_t* droppedFrames,
uint32_t* framesEncoded) override;
bool GetVideoDecoderStats(double* framerateMean,
double* framerateStdDev,
double* bitrateMean,
double* bitrateStdDev,
- uint32_t* discardedPackets) override;
+ uint32_t* discardedPackets,
+ uint32_t* framesDecoded) override;
bool GetAVStats(int32_t* jitterBufferDelayMs,
int32_t* playoutBufferDelayMs,
int32_t* avSyncOffsetMs) override;
bool GetRTPStats(unsigned int* jitterMs, unsigned int* cumulativeLost) override;
bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
uint32_t* jitterMs,
uint32_t* packetsReceived,
uint64_t* bytesReceived,
@@ -393,19 +394,25 @@ private:
*/
class ReceiveStreamStatistics : public StreamStatistics {
public:
/**
* Returns the number of discarded packets
* @param aOutDiscPackets: number of discarded packets
*/
void DiscardedPackets(uint32_t& aOutDiscPackets) const;
+ /**
+ * Returns the number of frames decoded
+ * @param aOutDiscPackets: number of frames decoded
+ */
+ void FramesDecoded(uint32_t& aFramesDecoded) const;
void Update(const webrtc::VideoReceiveStream::Stats& aStats);
private:
uint32_t mDiscardedPackets = 0;
+ uint32_t mFramesDecoded = 0;
};
/*
* Stores encoder configuration information and produces
* a VideoEncoderConfig from it.
*/
class VideoStreamFactory;
class VideoEncoderConfigBuilder {
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -3829,26 +3829,29 @@ PeerConnectionImpl::ExecuteStatsQuery_s(
}
// Lastly, fill in video decoder stats if this is video
if (!isAudio) {
double framerateMean;
double framerateStdDev;
double bitrateMean;
double bitrateStdDev;
uint32_t discardedPackets;
+ uint32_t framesDecoded;
if (mp.Conduit()->GetVideoDecoderStats(&framerateMean,
&framerateStdDev,
&bitrateMean,
&bitrateStdDev,
- &discardedPackets)) {
+ &discardedPackets,
+ &framesDecoded)) {
s.mFramerateMean.Construct(framerateMean);
s.mFramerateStdDev.Construct(framerateStdDev);
s.mBitrateMean.Construct(bitrateMean);
s.mBitrateStdDev.Construct(bitrateStdDev);
s.mDiscardedPackets.Construct(discardedPackets);
+ s.mFramesDecoded.Construct(framesDecoded);
}
}
query->report->mInboundRTPStreamStats.Value().AppendElement(s,
fallible);
// Fill in Contributing Source statistics
mp.GetContributingSourceStats(localId,
query->report->mRtpContributingSourceStats.Value());
break;