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

Revision 810, 7.5 KB checked in by pablo, 3 years ago (diff)
  • Bitrate switching for HTTP Streams
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 || item.file != itm.file || _stream.bytesLoaded == 0) {
82                                media = _video;
83                                _stream.checkPolicyFile = true;
84                                _stream.play(itm.file);
85                                _stream.pause();
86                        } else {
87                                replay = true;
88                        }
89
90                        _item = itm;
91                       
92                        setState(PlayerState.BUFFERING);
93                        if (replay){
94                                sendBufferEvent(0);
95                                sendBufferEvent(100);
96                                seekStream(0, false);
97                        } else {
98                                sendBufferEvent(0);
99                        }
100                        clearInterval(_positionInterval);
101                        _positionInterval = setInterval(positionHandler, 200);
102                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED);
103                        config.mute == true ? setVolume(0) : setVolume(config.volume);
104                }
105
106                /** Get metadata information from netstream class. **/
107                public function onClientData(dat:Object):void {
108                        if (dat.width) {
109                                _video.width = dat.width;
110                                _video.height = dat.height;
111                                resize(_width, _height);
112                        }
113                        if (dat.duration && item.duration < 0) {
114                                item.duration = dat.duration;
115                        }
116                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: dat});
117                }
118
119
120                /** Pause playback. **/
121                override public function pause():void {
122                        _stream.pause();
123                        super.pause();
124                }
125
126
127                /** Resume playing. **/
128                override public function play():void {
129                        if (!_positionInterval) {
130                                _positionInterval = setInterval(positionHandler, 100);
131                        }
132                        _stream.resume();
133                        super.play();
134                }
135
136
137                /** Interval for the position progress **/
138                protected function positionHandler():void {
139                        if (!_bandwidthChecked && _stream.bytesLoaded > 0) {
140                                _bandwidthChecked = true;
141                                setTimeout(checkBandwidth, _bandwidthTimeout, _stream.bytesLoaded);
142                        }
143                       
144                        var _streamTime:Number = Math.min(_stream.time, item.duration);
145                        _position = Math.round(_streamTime * 10) / 10;
146                        var bufferPercent:Number = _stream.bytesLoaded / _stream.bytesTotal * 100;
147                        var bufferTime:Number = _stream.bufferTime < (item.duration - _streamTime) ? _stream.bufferTime : Math.floor(Math.abs(item.duration - _streamTime));
148                        var bufferFill:Number = bufferTime == 0 ? 100 : Math.floor(_stream.bufferLength / bufferTime * 100);
149
150                       
151                        if (bufferFill < 25 && state == PlayerState.PLAYING) {
152                                _bufferFull = false;
153                                _stream.pause();
154                                setState(PlayerState.BUFFERING);
155                        } else if (bufferFill > 95 && state == PlayerState.BUFFERING && _bufferFull == false && bufferTime > 0) {
156                                _bufferFull = true;
157                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL);
158                        }
159
160                        if (!_bufferingComplete) {
161                                if (bufferPercent == 100 && _bufferingComplete == false) {
162                                        _bufferingComplete = true;
163                                }
164                                sendBufferEvent(bufferPercent);
165                        }
166
167                        if (position < item.duration) {
168                                if (state == PlayerState.PLAYING && position >= 0) {
169                                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: position, duration: item.duration});
170                                }
171                        } else if (item.duration > 0) {
172                                complete();
173                        }
174                }
175
176                private function checkBandwidth(lastLoaded:Number):void {
177                        var currentLoaded:Number = _stream.bytesLoaded;
178                        var bandwidth:Number = Math.ceil((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.ceil(_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                }
198
199                /** Seek to a new position. **/
200                override public function seek(pos:Number):void {
201                        seekStream(pos);
202                }
203               
204                private function seekStream(pos:Number, ply:Boolean=true):void {
205                        var bufferLength:Number = _stream.bytesLoaded / _stream.bytesTotal * item.duration;
206                        if (pos <= bufferLength) {
207                                super.seek(pos);
208                                clearInterval(_positionInterval);
209                                _positionInterval = undefined;
210                                _stream.seek(position);
211                                if (ply){
212                                        play();
213                                }
214                        }
215                }
216
217
218                /** Receive NetStream status updates. **/
219                protected function statusHandler(evt:NetStatusEvent):void {
220                        switch (evt.info.code) {
221                                case "NetStream.Play.Stop":
222                                        complete();
223                                        break;
224                                case "NetStream.Play.StreamNotFound":
225                                        error('Video not found or access denied: ' + item.file);
226                                        break;
227                        }
228                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: {status: evt.info.code}});
229                }
230
231
232                /** Destroy the video. **/
233                override public function stop():void {
234                        if (_stream.bytesLoaded < _stream.bytesTotal) {
235                                _stream.close();
236                        } else {
237                                _stream.pause();
238                                _stream.seek(0);
239                        }
240                        clearInterval(_positionInterval);
241                        _positionInterval = undefined;
242                        super.stop();
243                }
244
245
246                /** Set the volume level. **/
247                override public function setVolume(vol:Number):void {
248                        _transformer.volume = vol / 100;
249                        _stream.soundTransform = _transformer;
250                        super.setVolume(vol);
251                }
252        }
253}
Note: See TracBrowser for help on using the repository browser.