0

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!

1 Answers1

0

You could use a REST API to pass parameters to your network. Most of SDN controllers expose their API in order to interact with external applications.

Ryu REST API: https://osrg.github.io/ryu-book/en/html/rest_api.html Opendaylight REST API: https://wiki.opendaylight.org/view/OpenDaylight_Controller:REST_Reference_and_Authentication

Icaro Camelo
  • 382
  • 1
  • 10