source: trunk/fl5/src/com/longtailvideo/jwplayer/media/VideoMediaProvider.as @ 819

Revision 819, 7.5 KB checked in by pablo, 3 years ago (diff)
  • Fixed bug in HTTP and YouTube where seeking could result in strange buffering behavior in the controlbar.
  • Try/catch Arthropod log.
  • MediaProviders send position w/ jwplayerMediaBuffer events
  • Fixed bug in PNG Skins where the buffer wouldn't show correctly with a seek/offset.
RevLine 
[529]1package com.longtailvideo.jwplayer.media {
[364]2        import com.longtailvideo.jwplayer.events.MediaEvent;
3        import com.longtailvideo.jwplayer.model.PlayerConfig;
4        import com.longtailvideo.jwplayer.model.PlaylistItem;
[380]5        import com.longtailvideo.jwplayer.player.PlayerState;
[364]6        import com.longtailvideo.jwplayer.utils.NetClient;
[644]7       
[364]8        import flash.events.*;
9        import flash.media.*;
10        import flash.net.*;
11        import flash.utils.*;
[642]12
13
[529]14        /**
[642]15         * Wrapper for playback of progressively downloaded _video.
[529]16         **/
[364]17        public class VideoMediaProvider extends MediaProvider {
18                /** Video object to be instantiated. **/
[642]19                protected var _video:Video;
20                /** NetConnection object for setup of the video _stream. **/
21                protected var _connection:NetConnection;
[364]22                /** NetStream instance that handles the stream IO. **/
[642]23                protected var _stream:NetStream;
[364]24                /** Sound control object. **/
[642]25                protected var _transformer:SoundTransform;
[364]26                /** ID for the position interval. **/
[642]27                protected var _positionInterval:Number;
[650]28                /** Whether the buffer has filled **/
29                private var _bufferFull:Boolean;
[749]30                /** Whether the enitre video has been buffered **/
31                private var _bufferingComplete:Boolean;
[805]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;
[642]38
39
[364]40                /** Constructor; sets up the connection and display. **/
[370]41                public function VideoMediaProvider() {
[642]42                        super('video');
[370]43                }
[642]44
45
[370]46                public override function initializeMediaProvider(cfg:PlayerConfig):void {
47                        super.initializeMediaProvider(cfg);
[642]48                        _connection = new NetConnection();
49                        _connection.connect(null);
50                        _stream = new NetStream(_connection);
51                        _stream.addEventListener(NetStatusEvent.NET_STATUS, statusHandler);
52                        _stream.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
53                        _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler);
54                        _stream.bufferTime = config.bufferlength;
55                        _stream.client = new NetClient(this);
[805]56                        _transformer = new SoundTransform();
[642]57                        _video = new Video(320, 240);
58                        _video.smoothing = config.smoothing;
59                        _video.attachNetStream(_stream);
[364]60                }
[642]61
62
[364]63                /** Catch security errors. **/
64                protected function errorHandler(evt:ErrorEvent):void {
[523]65                        error(evt.text);
[364]66                }
[642]67
68
[364]69                /** Load content. **/
70                override public function load(itm:PlaylistItem):void {
[644]71                        var replay:Boolean;
[749]72                        _bufferFull = false;
73                        _bufferingComplete = false;
[805]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                       
[818]81                        if (!item
82                                        || item.file != itm.file
83                                        || _stream.bytesLoaded == 0
84                                        || (_stream.bytesLoaded < _stream.bytesTotal > 0))
85                        {
[642]86                                media = _video;
87                                _stream.checkPolicyFile = true;
[777]88                                _stream.play(itm.file);
[650]89                                _stream.pause();
[542]90                        } else {
[818]91                                if (itm.duration <= 0) { itm.duration = item.duration; }
92                                seekStream(itm.start, false);
[644]93                        }
[818]94
[819]95                        super.load(itm);
[818]96                        _item = itm;
[819]97
98                        config.mute == true ? setVolume(0) : setVolume(config.volume);
99
100                        setState(PlayerState.BUFFERING);
101                        sendBufferEvent(0);
[805]102                        clearInterval(_positionInterval);
[650]103                        _positionInterval = setInterval(positionHandler, 200);
[818]104
[364]105                }
[642]106
[364]107                /** Get metadata information from netstream class. **/
[806]108                public function onClientData(dat:Object):void {
[364]109                        if (dat.width) {
[642]110                                _video.width = dat.width;
111                                _video.height = dat.height;
[424]112                                resize(_width, _height);
[364]113                        }
[658]114                        if (dat.duration && item.duration < 0) {
115                                item.duration = dat.duration;
[406]116                        }
[364]117                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: dat});
118                }
[642]119
120
[364]121                /** Pause playback. **/
122                override public function pause():void {
[642]123                        _stream.pause();
[364]124                        super.pause();
125                }
[642]126
127
[364]128                /** Resume playing. **/
129                override public function play():void {
[642]130                        if (!_positionInterval) {
131                                _positionInterval = setInterval(positionHandler, 100);
[501]132                        }
[642]133                        _stream.resume();
[364]134                        super.play();
135                }
[642]136
137
[364]138                /** Interval for the position progress **/
[497]139                protected function positionHandler():void {
[805]140                        if (!_bandwidthChecked && _stream.bytesLoaded > 0) {
141                                _bandwidthChecked = true;
142                                setTimeout(checkBandwidth, _bandwidthTimeout, _stream.bytesLoaded);
143                        }
144                       
[653]145                        var _streamTime:Number = Math.min(_stream.time, item.duration);
146                        _position = Math.round(_streamTime * 10) / 10;
[642]147                        var bufferPercent:Number = _stream.bytesLoaded / _stream.bytesTotal * 100;
[653]148                        var bufferTime:Number = _stream.bufferTime < (item.duration - _streamTime) ? _stream.bufferTime : Math.floor(Math.abs(item.duration - _streamTime));
[805]149                        var bufferFill:Number = bufferTime == 0 ? 100 : Math.floor(_stream.bufferLength / bufferTime * 100);
[749]150
[653]151                       
[642]152                        if (bufferFill < 25 && state == PlayerState.PLAYING) {
[749]153                                _bufferFull = false;
[642]154                                _stream.pause();
155                                setState(PlayerState.BUFFERING);
[805]156                        } else if (bufferFill > 95 && state == PlayerState.BUFFERING && _bufferFull == false && bufferTime > 0) {
[749]157                                _bufferFull = true;
[497]158                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL);
[364]159                        }
[642]160
[776]161                        if (!_bufferingComplete) {
162                                if (bufferPercent == 100 && _bufferingComplete == false) {
163                                        _bufferingComplete = true;
[715]164                                }
[776]165                                sendBufferEvent(bufferPercent);
166                        }
167
168                        if (position < item.duration) {
[658]169                                if (state == PlayerState.PLAYING && position >= 0) {
[776]170                                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: position, duration: item.duration});
[519]171                                }
[364]172                        } else if (item.duration > 0) {
[497]173                                complete();
[364]174                        }
175                }
[642]176
[805]177                private function checkBandwidth(lastLoaded:Number):void {
178                        var currentLoaded:Number = _stream.bytesLoaded;
[810]179                        var bandwidth:Number = Math.ceil((currentLoaded - lastLoaded) / 1024) * 8 / (_bandwidthTimeout / 1000);
[805]180                        if (currentLoaded < _stream.bytesTotal) {
181                                if (bandwidth > 0) {
182                                        config.bandwidth = bandwidth;
183                                        var obj:Object = {bandwidth:bandwidth};
184                                        if (item.duration > 0) {
[810]185                                                obj.bitrate = Math.ceil(_stream.bytesTotal / 1024 * 8 / item.duration);
[805]186                                        }
187                                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: obj});
188                                }
189                                if (_bandwidthSwitch) {
190                                        _bandwidthSwitch = false;
191                                        if (item.currentLevel != item.getLevel(config.bandwidth, config.width)) {
192                                                load(item);
193                                                return;
194                                        }
195                                }
196                        }
197                        setTimeout(checkBandwidth, _bandwidthTimeout, currentLoaded);
198                }
[642]199
[364]200                /** Seek to a new position. **/
201                override public function seek(pos:Number):void {
[645]202                        seekStream(pos);
203                }
204               
205                private function seekStream(pos:Number, ply:Boolean=true):void {
[642]206                        var bufferLength:Number = _stream.bytesLoaded / _stream.bytesTotal * item.duration;
207                        if (pos <= bufferLength) {
[529]208                                super.seek(pos);
[642]209                                clearInterval(_positionInterval);
210                                _positionInterval = undefined;
211                                _stream.seek(position);
[645]212                                if (ply){
213                                        play();
214                                }
[529]215                        }
[364]216                }
[642]217
218
[364]219                /** Receive NetStream status updates. **/
220                protected function statusHandler(evt:NetStatusEvent):void {
221                        switch (evt.info.code) {
222                                case "NetStream.Play.Stop":
[497]223                                        complete();
[364]224                                        break;
225                                case "NetStream.Play.StreamNotFound":
[523]226                                        error('Video not found or access denied: ' + item.file);
[364]227                                        break;
228                        }
229                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: {status: evt.info.code}});
230                }
[642]231
232
[364]233                /** Destroy the video. **/
234                override public function stop():void {
[642]235                        if (_stream.bytesLoaded < _stream.bytesTotal) {
236                                _stream.close();
[364]237                        } else {
[642]238                                _stream.pause();
239                                _stream.seek(0);
[364]240                        }
[642]241                        clearInterval(_positionInterval);
242                        _positionInterval = undefined;
[364]243                        super.stop();
244                }
[642]245
246
[364]247                /** Set the volume level. **/
248                override public function setVolume(vol:Number):void {
[642]249                        _transformer.volume = vol / 100;
250                        _stream.soundTransform = _transformer;
[364]251                        super.setVolume(vol);
252                }
253        }
[370]254}
Note: See TracBrowser for help on using the repository browser.