Skip to content

Commit 4f8b326

Browse files
committed
decoder issue detector test
1 parent 1d9a872 commit 4f8b326

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/WebRTCIssueDetector.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
QualityLimitationsIssueDetector,
2525
UnknownVideoDecoderImplementationDetector,
2626
FrozenVideoTrackDetector,
27+
VideoDecoderIssueDetector,
2728
} from './detectors';
2829
import { CompositeRTCStatsParser, RTCStatsParser } from './parser';
2930
import createLogger from './utils/logger';
@@ -67,6 +68,7 @@ class WebRTCIssueDetector {
6768
new AvailableOutgoingBitrateIssueDetector(),
6869
new UnknownVideoDecoderImplementationDetector(),
6970
new FrozenVideoTrackDetector(),
71+
new VideoDecoderIssueDetector(),
7072
];
7173

7274
this.networkScoresCalculator = params.networkScoresCalculator ?? new DefaultNetworkScoresCalculator();
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import {
2+
IssueDetectorResult,
3+
WebRTCStatsParsed,
4+
} from '../types';
5+
import BaseIssueDetector, { BaseIssueDetectorParams } from './BaseIssueDetector';
6+
7+
interface VideoDecoderIssueDetectorParams extends BaseIssueDetectorParams {
8+
decodeTimePerFrameIncreaseSpeedThreshold?: number;
9+
minDecodeTimePerFrameIncreaseCases?: number;
10+
}
11+
12+
class VideoDecoderIssueDetector extends BaseIssueDetector {
13+
#decodeTimePerFrameIncreaseSpeedThreshold: number;
14+
15+
#minDecodeTimePerFrameIncreaseCases: number;
16+
17+
constructor(params: VideoDecoderIssueDetectorParams = {}) {
18+
super(params);
19+
this.#decodeTimePerFrameIncreaseSpeedThreshold = params.decodeTimePerFrameIncreaseSpeedThreshold ?? 1.05;
20+
this.#minDecodeTimePerFrameIncreaseCases = params.minDecodeTimePerFrameIncreaseCases ?? 3;
21+
}
22+
23+
performDetection(data: WebRTCStatsParsed): IssueDetectorResult {
24+
const { connection: { id: connectionId } } = data;
25+
const issues = this.processData(data);
26+
this.setLastProcessedStats(connectionId, data);
27+
return issues;
28+
}
29+
30+
private processData(data: WebRTCStatsParsed): IssueDetectorResult {
31+
const currentIncomeVideoStreams = data.video.inbound;
32+
const allLastProcessedStats = this
33+
.getAllLastProcessedStats(data.connection.id);
34+
35+
const issues: IssueDetectorResult = [];
36+
37+
currentIncomeVideoStreams.forEach((incomeVideoStream) => {
38+
const lastIncomeVideoStreamStats = allLastProcessedStats
39+
.map((connectionStats) => connectionStats.video.inbound.find(
40+
(videoStreamStats) => videoStreamStats.id === incomeVideoStream.id,
41+
))
42+
.filter((stats) => (stats?.framesDecoded || 0) > 0 && (stats?.totalDecodeTime || 0) > 0);
43+
44+
if (lastIncomeVideoStreamStats.length < this.#minDecodeTimePerFrameIncreaseCases) {
45+
return;
46+
}
47+
48+
const decodeTimePerFrame = lastIncomeVideoStreamStats
49+
.map((stats) => (stats!.totalDecodeTime * 1000) / stats!.framesDecoded);
50+
51+
const currentDecodeTimePerFrame = (incomeVideoStream.totalDecodeTime * 1000) / incomeVideoStream.framesDecoded;
52+
decodeTimePerFrame.push(currentDecodeTimePerFrame);
53+
54+
const mean = decodeTimePerFrame.reduce((acc, val) => acc + val, 0) / decodeTimePerFrame.length;
55+
const squaredDiffs = decodeTimePerFrame.map((val) => (val - mean) ** 2);
56+
const variance = squaredDiffs.reduce((acc, val) => acc + val, 0) / squaredDiffs.length;
57+
const volatility = Math.sqrt(variance);
58+
59+
console.log({
60+
decodeTimePerFrame,
61+
mean,
62+
variance,
63+
volatility,
64+
});
65+
});
66+
67+
return issues;
68+
}
69+
}
70+
71+
export default VideoDecoderIssueDetector;

src/detectors/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export { default as OutboundNetworkIssueDetector } from './OutboundNetworkIssueD
88
export { default as QualityLimitationsIssueDetector } from './QualityLimitationsIssueDetector';
99
export { default as UnknownVideoDecoderImplementationDetector } from './UnknownVideoDecoderImplementationDetector';
1010
export { default as FrozenVideoTrackDetector } from './FrozenVideoTrackDetector';
11+
export { default as VideoDecoderIssueDetector } from './VideoDecoderIssueDetector';

0 commit comments

Comments
 (0)