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