1
I have a client application called Dash.js, video player, that runs in an environment that emulates a SDN network, with switches and an Openflow controller.
This application adapts video quality according to user network bandwidth.
The class that determines whether the client will request the segment change to adapt the available bandwidth is 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 segment exchange occurs, a message is fired into the Openflow switch, so that 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 fire this message and receive on the Openflow switch?
Thank you!