How to send messages from a client application (Dash.js) to an Openflow Switch

Asked

Viewed 49 times

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!

1 answer

0

From what I understand, the AbrController has a method that is called by the player to determine what is the size of the band, internally it makes the calculation and returns a Promise.

In this case, you can modify the scope that is calling the method getPlaybackQuality of AbrController to return a file to you or to use the getPlaybackQuality for you to know if the quality has changed or not. The cool thing is for you to continue using the file to get this update.

I don’t like changing third-party source code but open source is for that right? Then another simpler step would be for you to trigger an event so the quality has changed.

Take a look at this Dispatcher it is quite simple to use and does not care about the hirearquia of objects, so you can shoot an event from anywhere and capture it anywhere.

But again, this can help you but at the same time can mess up your code a little bit since the method that returns the quality, returns you a.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.