UNPKG

@observertc/client-monitor-js

Version:

ObserveRTC Client Integration Javascript Library

1 lines 2.45 kB
export class StuckDecoderDetector{trackMonitor;static ISSUE_TYPE="stuck-decoder";name="stuck-decoder-detector";disabled=!1;issueKey;_stuckSince;_stuckTicks=0;_deadBytes=0;_plisSinceStuck=0;_sawAssembledFrames=!1;_alertOn=!1;_startedAt;constructor(t){this.trackMonitor=t,this.issueKey=`${StuckDecoderDetector.ISSUE_TYPE}-track-${t.track.id}`}get config(){return this.peerConnection.parent.config.stuckDecoderDetector}get peerConnection(){return this.trackMonitor.getPeerConnection()}update(){if(this.disabled)return;const t=this.trackMonitor.getInboundRtp();if(!t||"video"!==t.kind)return;if(this.trackMonitor.remoteOutboundTrackPaused)return this._reset("remote track paused");const e=t.deltaBytesReceived??0,s=t.deltaFramesDecoded;if(void 0===s||0<s)return this._reset("frames decoding");if((t.bitrate??0)<this.config.minBitrate)return this._reset("rtp not flowing");const i=Date.now();if(this._stuckSince??=i,this._stuckTicks+=1,this._deadBytes+=e,this._plisSinceStuck+=t.deltaPliCount??0,0<(t.deltaFramesReceived??0)&&(this._sawAssembledFrames=!0),this._alertOn)return;const r=i-this._stuckSince,n=1e3*(this.peerConnection.avgRttInSec??0);if(r<Math.max(this.config.thresholdInMs,this.config.rttMultiplier*n))return;if(this._stuckTicks<this.config.minStuckTicks)return;if(this._plisSinceStuck<this.config.minPliCount)return;this._alertOn=!0,this._startedAt=i;const c=void 0===t.deltaFramesReceived?"unknown":this._sawAssembledFrames?"decode":"assembly",o=this.peerConnection.parent;o.emit("stuck-decoder",{clientMonitor:o,trackMonitor:this.trackMonitor,variant:c,stuckForInMs:r,deadBytesReceived:this._deadBytes,pliCountSinceStuck:this._plisSinceStuck}),o.raiseIssue(this.issueKey,{type:StuckDecoderDetector.ISSUE_TYPE,payload:{peerConnectionId:this.peerConnection.peerConnectionId,trackId:this.trackMonitor.track.id,ssrc:t.ssrc,variant:c,stuckForInMs:r,deadBytesReceived:this._deadBytes,pliCountSinceStuck:this._plisSinceStuck,frameWidth:t.frameWidth,frameHeight:t.frameHeight,decoderImplementation:t.decoderImplementation}})}_reset(t){if(this._stuckSince=void 0,this._stuckTicks=0,this._deadBytes=0,this._plisSinceStuck=0,this._sawAssembledFrames=!1,!this._alertOn)return;this._alertOn=!1;const e=this.peerConnection.parent,s=e.activeIssues.get(this.issueKey);let i;s&&(i={...s.payload,durationInMs:this._startedAt?Date.now()-this._startedAt:void 0}),e.resolveIssue(this.issueKey,{comment:t,payload:i,resolvedAt:Date.now()}),this._startedAt=void 0}}