我有一个名为 Dash.js 的客户端应用程序,即视频播放器,它在模拟带有交换机和 openflow 控制器的 SDN 网络的环境中运行。
此应用程序使视频质量适应用户网络的带宽。
确定客户端是否会请求替换段以适应可用带宽的类是 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
};
我想要的是每次有段更改请求时,都会为openflow交换机触发一条消息,以便它可以向控制器发送一个packetin,控制器采取行动。
对我来说,现在的问题是客户端和 OpenFlow 交换机之间的这种通信交换。
有谁知道如何拍摄此消息并进入 openflow 开关?
谢谢!