I have a client application called Dash.js, video player, which runs in an environment that emulates an SDN network with switches and openflow controller.
This application adapts video quality to the bandwidth of the user's network .
The class that determines whether the client will request a replacement segment to adapt to 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 there is a request for segment change, a message is triggered for openflow switch, so that it can send a packetin to the controller and the controller take action.
For me, now, the problem is this exchange of communication between the client and the OpenFlow Switch.
Does anyone know how to shoot this message and get in openflow switch?
Thank you!