Changeset 805


Ignore:
Timestamp:
01/20/10 20:04:00 (3 years ago)
Author:
pablo
Message:
  • Updated PlaylistItems to store multiple quality levels
  • Implemented bandwidth detection and bitrate switching in VideoMediaProvider
Location:
trunk/fl5
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/fl5/src/com/longtailvideo/jwplayer/media/VideoMediaProvider.as

    r797 r805  
    2626                /** ID for the position interval. **/ 
    2727                protected var _positionInterval:Number; 
    28                 /** Load offset for bandwidth checking. **/ 
    29                 protected var _loadTimer:Number; 
    3028                /** Whether the buffer has filled **/ 
    3129                private var _bufferFull:Boolean; 
    3230                /** Whether the enitre video has been buffered **/ 
    3331                private var _bufferingComplete:Boolean; 
     32                /** Whether we have checked the bandwidth. **/ 
     33                private var _bandwidthChecked:Boolean; 
     34                /** Whether to switch on bandwidth detection **/ 
     35                private var _bandwidthSwitch:Boolean = true; 
     36                /** Bandwidth check interval **/ 
     37                private var _bandwidthTimeout:Number = 2000; 
    3438 
    3539 
     
    5054                        _stream.bufferTime = config.bufferlength; 
    5155                        _stream.client = new NetClient(this); 
     56                        _transformer = new SoundTransform(); 
    5257                        _video = new Video(320, 240); 
    5358                        _video.smoothing = config.smoothing; 
    5459                        _video.attachNetStream(_stream); 
    55                         _transformer = new SoundTransform(); 
    5660                } 
    5761 
     
    6872                        _bufferFull = false; 
    6973                        _bufferingComplete = false; 
     74                        if (itm.levels.length > 0) { 
     75                                itm.setLevel(itm.getLevel(config.bandwidth, config.width)); 
     76                                _bandwidthChecked = false; 
     77                        } else { 
     78                                _bandwidthChecked = true; 
     79                        } 
     80                         
    7081                        if (!item || item.file != itm.file || _stream.bytesLoaded == 0) { 
    7182                                media = _video; 
     
    8798                                sendBufferEvent(0); 
    8899                        } 
     100                        clearInterval(_positionInterval); 
    89101                        _positionInterval = setInterval(positionHandler, 200); 
    90                         _loadTimer = setTimeout(loadTimerComplete, 3000); 
    91102                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED); 
    92103                        config.mute == true ? setVolume(0) : setVolume(config.volume); 
    93104                } 
    94  
    95  
    96                 /** timeout for checking the bitrate. **/ 
    97                 protected function loadTimerComplete():void { 
    98                         var obj:Object = new Object(); 
    99                         obj.bandwidth = Math.round(_stream.bytesLoaded / 1024 / 3 * 8); 
    100                         if (item.duration) { 
    101                                 obj.bitrate = Math.round(_stream.bytesTotal / 1024 * 8 / item.duration); 
    102                         } 
    103                         sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: obj}); 
    104                 } 
    105  
    106105 
    107106                /** Get metadata information from netstream class. **/ 
     
    138137                /** Interval for the position progress **/ 
    139138                protected function positionHandler():void { 
     139                        if (!_bandwidthChecked && _stream.bytesLoaded > 0) { 
     140                                _bandwidthChecked = true; 
     141                                setTimeout(checkBandwidth, _bandwidthTimeout, _stream.bytesLoaded); 
     142                        } 
     143                         
    140144                        var _streamTime:Number = Math.min(_stream.time, item.duration); 
    141145                        _position = Math.round(_streamTime * 10) / 10; 
    142146                        var bufferPercent:Number = _stream.bytesLoaded / _stream.bytesTotal * 100; 
    143147                        var bufferTime:Number = _stream.bufferTime < (item.duration - _streamTime) ? _stream.bufferTime : Math.floor(Math.abs(item.duration - _streamTime)); 
    144                         var bufferFill:Number = bufferTime == 0 ? 100 : Math.ceil(_stream.bufferLength / bufferTime * 100); 
     148                        var bufferFill:Number = bufferTime == 0 ? 100 : Math.floor(_stream.bufferLength / bufferTime * 100); 
    145149 
    146150                         
     
    149153                                _stream.pause(); 
    150154                                setState(PlayerState.BUFFERING); 
    151                         } else if (bufferFill > 95 && state == PlayerState.BUFFERING && _bufferFull == false) { 
     155                        } else if (bufferFill > 95 && state == PlayerState.BUFFERING && _bufferFull == false && bufferTime > 0) { 
    152156                                _bufferFull = true; 
    153157                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL); 
     
    170174                } 
    171175 
     176                private function checkBandwidth(lastLoaded:Number):void { 
     177                        var currentLoaded:Number = _stream.bytesLoaded; 
     178                        var bandwidth:Number = ((currentLoaded - lastLoaded) / 1024) * 8 / (_bandwidthTimeout / 1000); 
     179                        if (currentLoaded < _stream.bytesTotal) { 
     180                                if (bandwidth > 0) { 
     181                                        config.bandwidth = bandwidth; 
     182                                        var obj:Object = {bandwidth:bandwidth}; 
     183                                        if (item.duration > 0) { 
     184                                                obj.bitrate = Math.round(_stream.bytesTotal / 1024 * 8 / item.duration); 
     185                                        } 
     186                                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: obj}); 
     187                                } 
     188                                if (_bandwidthSwitch) { 
     189                                        _bandwidthSwitch = false; 
     190                                        if (item.currentLevel != item.getLevel(config.bandwidth, config.width)) { 
     191                                                load(item); 
     192                                                return; 
     193                                        } 
     194                                } 
     195                        } 
     196                        setTimeout(checkBandwidth, _bandwidthTimeout, currentLoaded); 
     197                } 
    172198 
    173199                /** Seek to a new position. **/ 
     
    212238                                _stream.seek(0); 
    213239                        } 
    214                         _loadTimer = undefined; 
    215240                        clearInterval(_positionInterval); 
    216241                        _positionInterval = undefined; 
  • trunk/fl5/src/com/longtailvideo/jwplayer/model/PlayerConfig.as

    r730 r805  
    1818                protected var _playlistfile:String      = null; 
    1919 
    20                 protected var _autostart:Boolean                = false;  
     20                protected var _autostart:Boolean        = false;  
     21                protected var _bandwidth:Number         = 1500; 
    2122                protected var _bufferlength:Number      = 5;  
    22                 protected var _displaytitle:Boolean     = true;  
     23                protected var _displaytitle:Boolean = true;  
    2324                protected var _fullscreen:Boolean       = false; 
    2425                protected var _item:Number                      = 0; 
    25                 protected var _linktarget:String                = "_blank"; 
    26                 protected var _mute:Boolean                     = false; 
    27                 protected var _repeat:String                    = RepeatOptions.NONE;  
     26                protected var _linktarget:String        = "_blank"; 
     27                protected var _mute:Boolean             = false; 
     28                protected var _repeat:String            = RepeatOptions.NONE;  
    2829                protected var _shuffle:Boolean          = false;  
    29                 protected var _smoothing:Boolean                = true; 
     30                protected var _smoothing:Boolean        = true; 
     31                 
    3032                //TODO: Move to ENUM class 
    31                 protected var _stretching:String                = "uniform";  
    32                 protected var _volume:Number                    = 90; 
     33                protected var _stretching:String        = "uniform";  
     34                protected var _volume:Number            = 90; 
    3335 
    3436                protected var _backcolor:Color          = null; 
    3537                protected var _frontcolor:Color         = null; 
    3638                protected var _lightcolor:Color         = null; 
    37                 protected var _screencolor:Color                = null; 
     39                protected var _screencolor:Color        = null; 
    3840 
    3941                //TODO: Move to ENUM class 
    40                 protected var _controlbar:String                = "bottom"; 
    41                 protected var _dock:Boolean                     = true; 
    42                 protected var _height:Number                    = 400; 
    43                 protected var _icons:Boolean                    = true; 
     42                protected var _controlbar:String        = "bottom"; 
     43                protected var _dock:Boolean             = true; 
     44                protected var _height:Number            = 400; 
     45                protected var _icons:Boolean            = true; 
    4446                protected var _logo:String                      = null; 
    4547                protected var _playlist:String          = "none"; 
    4648                protected var _playlistsize:Number      = 180; 
    4749                protected var _skin:String                      = null; 
    48                 protected var _width:Number                     = 280; 
     50                protected var _width:Number             = 280; 
    4951                 
    5052                protected var _plugins:String           = ""; //plugins initial string 
    5153                protected var _pluginConfig:Object      = {}; 
    5254                 
    53                 protected var _playerready:String               = ""; 
     55                protected var _playerready:String       = ""; 
    5456                protected var _debug:String                     = Logger.NONE; 
    5557                 
     
    282284                public function set autostart(x:Boolean):void { _autostart = x; } 
    283285 
     286                /** Automatically start the player on load. @default false **/ 
     287                public function get bandwidth():Number { return _bandwidth; } 
     288                public function set bandwidth(x:Number):void { _bandwidth = x; } 
     289 
    284290                /**  
    285291                 * Number of seconds of the file that has to be loaded before starting. Set this to a low value to enable instant-start and to a  
  • trunk/fl5/src/com/longtailvideo/jwplayer/model/PlaylistItem.as

    r542 r805  
    1111                public var description:String   = ""; 
    1212                public var duration:Number              = -1; 
    13                 public var file:String                  = ""; 
    1413                public var image:String                 = ""; 
    1514                public var link:String                  = ""; 
     
    2120                public var provider:String              = ""; 
    2221                 
     22                protected var _file:String                      = ""; 
     23                protected var _currentLevel:Number      = -1; 
     24                protected var _levels:Array                     = []; 
     25                 
    2326                public function PlaylistItem(obj:Object = null) { 
    2427                        for (var itm:String in obj) { 
    2528                                if (this[itm] && typeof(this[itm]) == typeof(0)) { 
    2629                                        this[itm] = Number(obj[itm]); 
     30                                } else if (itm == "levels" && obj[itm] is Array) { 
     31                                        var levels:Array = obj[itm] as Array; 
     32                                        for each (var level:Object in levels) { 
     33                                                if (level['file'] && level['bitrate'] && level['width']) { 
     34                                                        addLevel(new PlaylistItemLevel(level['file'], level['bitrate'], level['width'])); 
     35                                                } 
     36                                        } 
    2737                                } else { 
    2838                                        this[itm] = obj[itm]; 
    2939                                } 
     40                        } 
     41                } 
     42 
     43                /** File property is now a getter, to take levels into account **/ 
     44                public function get file():String { 
     45                        if (_levels.length > 0 && _currentLevel > -1 && _currentLevel < _levels.length) { 
     46                                return (_levels[_currentLevel] as PlaylistItemLevel).file; 
     47                        } else { 
     48                                return _file; 
     49                        } 
     50                } 
     51                 
     52                /** File setter.  Note, if levels are defined, this will be ignored. **/ 
     53                public function set file(f:String):void { 
     54                        _file = f; 
     55                } 
     56                 
     57                /** The quality levels associated with this playlist item **/ 
     58                public function get levels():Array { 
     59                        return _levels; 
     60                } 
     61                 
     62                /** Insert an additional bitrate level, keeping the array sorted from highest to lowest. **/ 
     63                public function addLevel(newLevel:PlaylistItemLevel):void { 
     64                        if (_currentLevel < 0) _currentLevel = 0; 
     65                        for (var i:Number = 0; i < _levels.length; i++) { 
     66                                var level:PlaylistItemLevel = _levels[i] as PlaylistItemLevel; 
     67                                if (newLevel.bitrate > level.bitrate) { 
     68                                        _levels.splice(i, 0, newLevel); 
     69                                        return; 
     70                                } else if (newLevel.bitrate == level.bitrate && newLevel.width > level.width) { 
     71                                        _levels.splice(i, 0, newLevel); 
     72                                        return; 
     73                                } 
     74                        } 
     75                         
     76                        _levels.push(newLevel); 
     77                } 
     78 
     79                public function get currentLevel():Number { 
     80                        return _currentLevel; 
     81                } 
     82                 
     83                public function getLevel(bitrate:Number, width:Number):Number { 
     84                        for (var i:Number=0; i < _levels.length; i++) { 
     85                                var level:PlaylistItemLevel = _levels[i] as PlaylistItemLevel; 
     86                                if (bitrate >= level.bitrate && width >= level.width * 0.9) { 
     87                                        return i; 
     88                                } 
     89                        } 
     90                        return _levels.length - 1; 
     91                } 
     92                 
     93                /** Set this PlaylistItem's level to match the given bitrate and height. **/ 
     94                public function setLevel(newLevel:Number):void { 
     95                        if (newLevel >= 0 && newLevel < _levels.length) { 
     96                                _currentLevel = newLevel; 
     97                        } else { 
     98                                throw(new Error("Level index out of bounds")); 
    3099                        } 
    31100                } 
  • trunk/fl5/src/com/longtailvideo/jwplayer/parsers/MediaParser.as

    r540 r805  
    2222                 **/ 
    2323                public static function parseGroup(obj:XML, itm:Object):Object { 
     24                        var ytp:Boolean = false; 
     25 
    2426                        for each (var i:XML in obj.children()) { 
    2527                                if (i.namespace().prefix == MediaParser.PREFIX) { 
     
    3739                                                        if (i.children().length() > 0) { 
    3840                                                                itm = MediaParser.parseGroup(i, itm); 
     41                                                        } 
     42                                                        if (i.@width && i.@bitrate) { 
     43                                                                if (!itm.levels) { 
     44                                                                        itm.levels = new Array(); 
     45                                                                } 
     46                                                                itm.levels.push({ 
     47                                                                        width:i.@width.toString(), 
     48                                                                        bitrate:i.@bitrate.toString(), 
     49                                                                        file:i.@url.toString() 
     50                                                                }); 
    3951                                                        } 
    4052                                                        break; 
     
    5668                                                case 'player': 
    5769                                                        if (i.@url.indexOf('youtube.com') > 0) { 
    58                                                                 var ytp:Boolean = true; 
     70                                                                ytp = true; 
    5971                                                                itm['file'] = i.@url.toString(); 
    6072                                                        } 
  • trunk/fl5/src/com/longtailvideo/jwplayer/player/PlayerV4Emulation.as

    r773 r805  
    1313        import com.longtailvideo.jwplayer.model.Model; 
    1414        import com.longtailvideo.jwplayer.model.PlaylistItem; 
     15        import com.longtailvideo.jwplayer.model.PlaylistItemLevel; 
    1516        import com.longtailvideo.jwplayer.plugins.IPlugin; 
    1617        import com.longtailvideo.jwplayer.plugins.PluginConfig; 
     
    349350                        cfg['version'] = _player.version; 
    350351                        cfg['item'] = _player.playlist.currentIndex; 
     352                        cfg['level'] = _player.playlist.currentItem.currentLevel; 
    351353                         
    352354                        return cfg; 
     
    386388                        for (var i:String in item) { 
    387389                                obj[i] = item[i]; 
     390                        } 
     391                         
     392                        if (item.levels.length > 0) { 
     393                                obj['levels'] = []; 
     394                                for each (var level:PlaylistItemLevel in item.levels) { 
     395                                        obj['levels'].push({url:level.file, bitrate:level.bitrate, width:level.width}); 
     396                                } 
    388397                        } 
    389398                         
  • trunk/fl5/src/com/longtailvideo/jwplayer/player/PlayerVersion.as

    r802 r805  
    33         
    44        public class PlayerVersion { 
    5                 protected static var _version:String = "5.1.802"; 
     5                protected static var _version:String = "5.1.805"; 
    66                 
    77                public static function get version():String { 
  • trunk/fl5/src/com/longtailvideo/jwplayer/view/View.as

    r801 r805  
    355355                                        _plugins[id] = plugDO; 
    356356                                        _pluginsLayer.addChild(plugDO); 
    357                                                 //_pluginsLayer[id] = plugDO; 
    358357                                } 
    359358                        } catch (e:Error) { 
Note: See TracChangeset for help on using the changeset viewer.