I have a client application called Dash.js, a video player, that runs in an environment that emulates an SDN network, with switches and an openflow controller.
This application adapts the quality of the video according to the user's network bandwidth.
The class that determines whether the client will request the segment change to fit the available bandwidth is the AbrController.js.
MediaPlayer.dependencies.AbrController = function () {
"use strict";
var autoSwitchBitrate = true,
qualityDict = {},
confidenceDict = {},
getInternalQuality = function (type) {
var quality;
if (!qualityDict.hasOwnProperty(type)) {
qualityDict[type] = 0;
}
quality = qualityDict[type];
return quality;
},
setInternalQuality = function (type, value) {
qualityDict[type] = value;
},
getInternalConfidence = function (type) {
var confidence;
if (!confidenceDict.hasOwnProperty(type)) {
confidenceDict[type] = 0;
}
confidence = confidenceDict[type];
return confidence;
},
setInternalConfidence = function (type, value) {
confidenceDict[type] = value;
};
return {
debug: undefined,
abrRulesCollection: undefined,
manifestExt: undefined,
metricsModel: undefined,
metricsBaselinesModel: undefined,
getAutoSwitchBitrate: function () {
return autoSwitchBitrate;
},
setAutoSwitchBitrate: function (value) {
autoSwitchBitrate = value;
},
getMetricsFor: function (data) {
var deferred = Q.defer(),
self = this;
self.manifestExt.getIsVideo(data).then(
function (isVideo) {
if (isVideo) {
deferred.resolve(self.metricsModel.getMetricsFor("video"));
} else {
self.manifestExt.getIsAudio(data).then(
function (isAudio) {
if (isAudio) {
deferred.resolve(self.metricsModel.getMetricsFor("audio"));
} else {
deferred.resolve(self.metricsModel.getMetricsFor("stream"));
}
}
);
}
}
);
return deferred.promise;
},
getMetricsBaselineFor: function (data) {
var deferred = Q.defer(),
self = this;
self.manifestExt.getIsVideo(data).then(
function (isVideo) {
if (isVideo) {
deferred.resolve(self.metricsBaselinesModel.getMetricsBaselineFor("video"));
} else {
self.manifestExt.getIsAudio(data).then(
function (isAudio) {
if (isAudio) {
deferred.resolve(self.metricsBaselinesModel.getMetricsBaselineFor("audio"));
} else {
deferred.resolve(self.metricsBaselinesModel.getMetricsBaselineFor("stream"));
//self.debug.log("GET STREAM.");
}
}
);
}
}
);
return deferred.promise;
},
getPlaybackQuality: function (type, data, availableRepresentations) {
var self = this,
deferred = Q.defer(),
newQuality = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,
newConfidence = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,
i,
len,
funcs = [],
req,
values,
quality,
confidence;
quality = getInternalQuality(type);
confidence = getInternalConfidence(type);
//self.debug.log("ABR enabled? (" + autoSwitchBitrate + ")");
if (autoSwitchBitrate) {
//self.debug.log("Check ABR rules.");
self.getMetricsFor(data).then(
function (metrics) {
self.getMetricsBaselineFor(data).then(
function (metricsBaseline) {
self.abrRulesCollection.getRules().then(
function (rules) {
for (i = 0, len = rules.length; i < len; i += 1) {
funcs.push(rules[i].checkIndex(quality, metrics, data, metricsBaseline, availableRepresentations));
}
Q.all(funcs).then(
function (results) {
//self.debug.log(results);
values = {};
values[MediaPlayer.rules.SwitchRequest.prototype.STRONG] = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE;
values[MediaPlayer.rules.SwitchRequest.prototype.WEAK] = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE;
values[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT] = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE;
for (i = 0, len = results.length; i < len; i += 1) {
req = results[i];
if (req.quality !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE) {
values[req.priority] = Math.min(values[req.priority], req.quality);
}
}
if (values[MediaPlayer.rules.SwitchRequest.prototype.WEAK] !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE) {
newConfidence = MediaPlayer.rules.SwitchRequest.prototype.WEAK;
newQuality = values[MediaPlayer.rules.SwitchRequest.prototype.WEAK];
}
if (values[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT] !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE) {
newConfidence = MediaPlayer.rules.SwitchRequest.prototype.DEFAULT;
newQuality = values[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT];
}
if (values[MediaPlayer.rules.SwitchRequest.prototype.STRONG] !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE) {
newConfidence = MediaPlayer.rules.SwitchRequest.prototype.STRONG;
newQuality = values[MediaPlayer.rules.SwitchRequest.prototype.STRONG];
}
if (newQuality !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE && newQuality !== undefined) {
quality = newQuality;
}
if (newConfidence !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE && newConfidence !== undefined) {
confidence = newConfidence;
}
self.manifestExt.getRepresentationCount(data).then(
function (max) {
// be sure the quality valid!
if (quality < 0) {
quality = 0;
}
// zero based
if (quality >= max) {
quality = max - 1;
}
if (confidence != MediaPlayer.rules.SwitchRequest.prototype.STRONG &&
confidence != MediaPlayer.rules.SwitchRequest.prototype.WEAK) {
confidence = MediaPlayer.rules.SwitchRequest.prototype.DEFAULT;
}
setInternalQuality(type, quality);
//self.debug.log("New quality of " + quality);
setInternalConfidence(type, confidence);
//self.debug.log("New confidence of " + confidence);
deferred.resolve({quality: quality, confidence: confidence});
}
);
}
);
}
);
}
);
}
);
} else {
self.debug.log("Unchanged quality of " + quality);
deferred.resolve({quality: quality, confidence: confidence});
}
return deferred.promise;
},
setPlaybackQuality: function (type, newPlaybackQuality) {
var quality = getInternalQuality(type);
if (newPlaybackQuality !== quality) {
setInternalQuality(type, newPlaybackQuality);
}
},
getQualityFor: function (type) {
return getInternalQuality(type);
}
};
};
MediaPlayer.dependencies.AbrController.prototype = {
constructor: MediaPlayer.dependencies.AbrController
};
What I want is that every time a request for thread exchange occurs, a message is thrown to the openflow switch, so it can send a packetin to the controller and the controller takes action.
For me, now, the problem lies in this exchange of communication between the client and the Openflow Switch.
Would anyone know how to trigger this message and receive on the openflow switch?
Thank you!