All files / dash.js/src/streaming/rules/abr DroppedFramesRule.js

33.33% Statements 12/36
25% Branches 5/20
100% Functions 2/2
34.28% Lines 12/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71            4x 4x       3x 3x   3x 2x     1x 1x 1x                                                                                 4x       4x     1x    
import FactoryMaker from '../../../core/FactoryMaker.js';
import SwitchRequest from '../SwitchRequest.js';
import Settings from '../../../core/Settings.js';
 
function DroppedFramesRule() {
 
    const context = this.context;
    const settings = Settings(context).getInstance();
    let instance;
 
    function getSwitchRequest(rulesContext) {
        const switchRequest = SwitchRequest(context).create();
        switchRequest.rule = this.getClassName();
 
        if (!rulesContext || !rulesContext.hasOwnProperty('getDroppedFramesHistory')) {
            return switchRequest;
        }
 
        const droppedFramesHistory = rulesContext.getDroppedFramesHistory();
        if (!droppedFramesHistory) {
            return switchRequest
        }
        const streamId = rulesContext.getStreamInfo().id;
        const mediaInfo = rulesContext.getMediaInfo();
        const abrController = rulesContext.getAbrController();
        const droppedFramesHistoryData = droppedFramesHistory.getFrameHistory(streamId);
 
        if (!droppedFramesHistoryData || Object.keys(droppedFramesHistoryData).length === 0) {
            return switchRequest;
        }
 
        let droppedFrames = 0;
        let totalFrames = 0;
        const representations = abrController.getPossibleVoRepresentationsFilteredBySettings(mediaInfo, true);
        let newRepresentation = null;
 
        //No point in measuring dropped frames for the first index.
        for (let i = 1; i < representations.length; i++) {
            const currentRepresentation = representations[i];
            if (currentRepresentation && droppedFramesHistoryData[currentRepresentation.id]) {
                droppedFrames = droppedFramesHistoryData[currentRepresentation.id].droppedVideoFrames;
                totalFrames = droppedFramesHistoryData[currentRepresentation.id].totalVideoFrames;
 
                if (totalFrames > settings.get().streaming.abr.rules.droppedFramesRule.parameters.minimumSampleSize && droppedFrames / totalFrames > settings.get().streaming.abr.rules.droppedFramesRule.parameters.droppedFramesPercentageThreshold) {
                    newRepresentation = representations[i - 1];
                    break;
                }
            }
        }
        if (newRepresentation) {
            switchRequest.representation = newRepresentation;
            switchRequest.priority = settings.get().streaming.abr.rules.droppedFramesRule.priority;
            switchRequest.reason = {
                droppedFrames,
                message: `[DroppedFramesRule]: Switching to index ${newRepresentation.absoluteIndex}. Dropped Frames: ${droppedFrames}, Total Frames: ${totalFrames}`
            };
        }
 
        return switchRequest;
    }
 
    instance = {
        getSwitchRequest
    };
 
    return instance;
}
 
DroppedFramesRule.__dashjs_factory_name = 'DroppedFramesRule';
export default FactoryMaker.getClassFactory(DroppedFramesRule);