Changeset 1280


Ignore:
Timestamp:
09/17/10 11:23:53 (3 years ago)
Author:
jeroen
Message:

fixed a bug in RTMPT error handling. Fixed a bug in HTTP continuous bitrate switching. Fixed a bug for playlist PNG rollovers without itemActive element. Added logic for hiding the image/description of playlist buttons when the button is <40px high or <240px wide. Added RST documentation on HTTP _droppedframes, HTTP DVR, RTMP DVRCast, RTMP _droppedframes, RTMP Tunneling and small playlist button element hiding.

Location:
trunk/fl5
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/fl5/doc/publishers/conf.py

    r1104 r1280  
    3030 
    3131# The full version, including alpha/beta/rc tags. 
    32 release = '5.2' 
     32release = '5.3' 
    3333 
    3434# List of documents that shouldn't be included in the build. 
  • trunk/fl5/doc/publishers/httpstreaming.rst

    r1120 r1280  
    44==================== 
    55 
    6 Both MP4 and FLV videos can be played back with a mechanism called HTTP Pseudostreaming. This mechanism allows your viewers to seek to not-yet downloaded parts of a video. Youtube is an example site that offers this functionality. HTTP pseudostreaming is enabled by setting the :ref:`option <options>` *provider=http* in your player. 
    7  
    8 HTTP pseudostreaming combines the advantages of straight HTTP downloads (it passes any firewall, viewers on bad connections can simply wait for the download) with the ability to seek to non-downloaded parts. The only drawbacks of HTTP Pseudostreaming compared to Flash's official :ref:`rtmpstreaming` are its reduced security (HTTP is easier to sniff than RTMP) and long loading times when seeking in large videos (> 15 minutes). 
    9  
    10 HTTP Pseudostreaming should not be confused with HTTP Dynamic Streaming. The latter is a brand-new mechanism currently being developed by Adobe that works by chopping up the original video in so-called *chunks* of a few seconds each. The videoplayer seamlessly glues these chunks together again. The JW Player does **not yet** support HTTP Dynamic Streaming. 
     6Both MP4 and FLV videos can be played back with a mechanism called *HTTP Pseudostreaming*. This mechanism allows your viewers to seek to not-yet downloaded parts of a video. Youtube is an example site that offers this functionality. HTTP pseudostreaming is enabled by setting the :ref:`option <options>` *provider=http* in your player. 
     7 
     8HTTP pseudostreaming combines the advantages of straight HTTP downloads (it passes any firewall, viewers on bad connections can simply wait for the download) with the ability to seek to non-downloaded parts. The drawbacks of HTTP Pseudostreaming compared to Flash's official :ref:`rtmpstreaming` are its reduced security (HTTP is easier to sniff than RTMP) and long loading times when seeking in large videos (> 15 minutes). 
     9 
     10HTTP Pseudostreaming should not be confused with HTTP Dynamic Streaming. The latter is a brand-new mechanism solely supported by the Flash Plugin 10.1+ that works by chopping up the original video in so-called *chunks* of a few seconds each. The videoplayer seamlessly glues these chunks together again. The JW Player does **not yet** support HTTP Dynamic Streaming. 
    1111 
    1212 
     
    2121Several CDN's (Content Delivery Networks) support HTTP Pseudostreaming as well. We have done succesfull tests with `Bitgravity <http://www.bitgravity.com>`_, `CDNetworks <http://www.cdnetworks.com>`_, `Edgecast <http://www.edgecastcdn.com>`_ and `Limelight <http://llnw.com>`_. 
    2222 
    23 Instead of using a serverside module, pseudostreaming can also be enabled by using a serverside script (in e.g. PHP or .NET). We do not advise this, since such a script consumes a lot of resources, has security implications and can only be used with FLV files. A much-used serverside script for pseudostreaming is `Xmoov-PHP <http://xmoov.com/xmoov-php/>`_. 
     23In addition to using a serverside module, pseudostreaming can be enabled by using a serverside script (in e.g. PHP or .NET). We do not advise this, since such a script consumes a lot of resources, has security implications and can only be used with FLV files. A much-used serverside script for pseudostreaming is `Xmoov-PHP <http://xmoov.com/xmoov-php/>`_. 
    2424 
    2525 
     
    6464* The `H264 streaming module <http://h264.code-shop.com/trac/wiki>`_ uses *http.startparam=starttime* for MP4 videos. 
    6565* `Bitgravity <http://www.bitgravity.com>`_ uses *http.startparam=apstart* for FLV videos and *http.startparam=starttime* for MP4 videos. 
    66 * `Edgecast <http://www.edgecastcdn.com>`_ uses *http.startparam=ec_seek* for FLV videos. 
     66* `Edgecast <http://www.edgecastcdn.com>`_ uses *http.startparam=ec_seek* for both FLV and MP4 videos (presuming bytes for FLV and seconds for MP4). 
    6767* `Limelight <http://llnw.com>`_ uses *http.startparam=fs* for FLV videos. 
    6868 
     
    130130* Fits the *bandwidth* of the server » client connection. 
    131131* Fits the *width* of the player's display (or, to be precise, is not more than 20% larger). 
     132* Does not result in more than 25% of *frames dropped* at any time (for example, if your video is 30fps, a level that results in 8fps dropped will get blacklisted). 
    132133 
    133134As a viewer continues to watch the video, the player re-examines its decision (and might switch) in response to certain events: 
     
    136137* On a **fullscreen** switch, since the *width* of the display then drastically changes. For example, when a viewer goes fullscreen and has sufficient bandwidth, the player might serve an HD version of the video. 
    137138* On every **seek** in the video. Since the player has to rebuffer-the stream anyway, it takes the opportunity to also check if bandwidth conditions have not changed. 
     139* In the event where **framedrops** account for more than 25% of the frames of the video. The player continously monitors this metric (ruling out any one-time spikes). When 25% of frames are dropped, the current level is permanently blacklisted - i.e. it will not be used for the remainder of the playback session. 
    138140 
    139141Note that the player will not do a bandwidth switch if extreme bandwidth changes cause the video to re-buffer. In practice, we found such a heuristic to cause continous switching and an awful viewing experience. :ref:`rtmpstreaming` on the other hand, is able to switch seamlessly in response to bandwidth fluctuations. 
     
    163165         </media:group> 
    164166         <jwplayer:provider>http</jwplayer:provider> 
    165          <jwplayer:http.startparam>apstart</jwplayer:http.startparam> 
     167         <jwplayer:http.startparam>starttime</jwplayer:http.startparam> 
    166168       </item> 
    167169    
     
    172174 
    173175* The *bitrate* attributes must be in kbps, as defined by the `mRSS spec <http://video.search.yahoo.com/mrss>`_. The *width* attribute is in pixels. 
    174 * It is recommended to order the streams by quality, the best one at the beginning. Most RSS readers will pick this one. 
     176* It is recommended to order the streams by quality, the best one at the beginning. Most RSS readers will pick this one. The JW Player will do an internal sorting though, so the order is not important for the player. 
    175177* The four levels displayed in this feed are actually what we recommend for bitrate switching of widescreen MP4 videos. For 4:3 videos or FLV videos, you might want to increase the bitrates or decrease the dimensions a little. 
    176178* Some publishers only modify the bitrate when encoding multiple levels. The player can work with this, but modifying both the bitrate + dimensions allows for more variation between the levels (and re-use of videos, e.g. the smallest one for streaming to phones). 
    177179* The *media:group* element here is optional, but it organizes the video links a little. 
     180 
     181 
     182Live DVR Streaming 
     183------------------ 
     184 
     185The JW Player supports Live HTTP DVR streaming as offered by the `Bitgravity CDN <http://bitgravity.com>`_. This works as follows: 
     186 
     187* The player loads a stream, simply as HTTP download. The server returns a header saying the stream is 1GB+ long, so the Flash plugin will continue downloading the file.  
     188* On the server side, bytes are appended to the file as they come in from the live ingestion point. 
     189* The player will start with a duration of 0 seconds for the stream, and then simply use a timer to increase the duration of the stream. 
     190* Since HTTP video downloads are kept in memory, it is possible to seek back to the point where you began watching the live stream. All that time, the duration will continue to grow, so you'll also be able to instantly jump back to the **live** head again. 
     191 
     192Example 
     193^^^^^^^ 
     194 
     195The HTTP live DVR streaming mechanism is enabled by setting the player option **http.dvr** to *true*. Here is an example embed code, using the  :ref:`SWFObject embed method <embedding>`: 
     196 
     197.. code-block:: html 
     198 
     199   <div id='container'>The player will be placed here</div> 
     200 
     201   <script type="text/javascript"> 
     202     var flashvars = {  
     203       file:'http://bglive-a.bitgravity.com/tatamkt/testing/ld', 
     204       provider:'http', 
     205       'http.dvr':'true' 
     206     }; 
     207 
     208     swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,  
     209      {allowfullscreen:'true',allowscriptaccess:'always'}, 
     210      {id:'jwplayer',name:'jwplayer'} 
     211     ); 
     212   </script> 
     213 
  • trunk/fl5/doc/publishers/releasenotes.rst

    r1152 r1280  
    44Release Notes 
    55============= 
     6 
     7Version 5.3 
     8=========== 
     9 
     10Build 1257 
     11---------- 
     12 
     13New Features 
     14++++++++++++ 
     15 
     16* Included framedrop handling for both HTTP and RTMP streaming, allowing switches in case of insufficient client resources (e.g. a netbook attempting to play an HD stream. 
     17* Automatic fallback to Tunneled RTMP / RTMPe (in case regular RTMP is blocked). 
     18* RTMP dynamic streaming can now be setup together with loadbalancing (using a SMIL XML file). 
     19* RTMP DVR now using Adobe's official DVRCast application instead of a custom serverside script. 
     20* Support for HTTP DVR streaming as offered by the Bitgravity CDN. 
     21* With PNG skinning, the description and image of playlist buttons are automatically hidden when the playlistbutton is less than 40px high and/or less than 240px wide. 
     22 
     23Bug Fixes 
     24+++++++++ 
     25 
     26* Fixed a bug that caused current bandwidth not to store in a cookie, resulting in continous bitrate switching after 2 seconds. 
     27* Fixed a bug that caused the duration textfield of a playlistitem would not be placed to the right. 
     28* Fixed a bug that caused PNG skin playlists not to show the item.png on rollout if there was no itemActive. 
     29*  
    630 
    731Version 5.2 
  • trunk/fl5/doc/publishers/rtmpstreaming.rst

    r1209 r1280  
    88* RTMP can do live streaming - people can watch your video while it is being recorded. 
    99* With RTMP, viewers can seek to not-yet-downloaded parts of a video. This is especially useful for longer-form content (> 10 minutes). 
    10 * Videos delivered over RTMP (and its secure brother, RTMPE) are harder to steal than videos delivered over regular HTTP. 
    11  
    12 However, do note that RTMP has its disadvantages too. Especially since the introduction of :ref:`httpstreaming` (which also offer seeking to not-yet-downloaded parts), RTMP is not the only option for professional video delivery. Some drawbacks to be aware of: 
    13  
    14 * RTMP is a different protocol than HTTP and is sent over a different port (1935 instead of 80). Therefore, RTMP is frequently blocked by (corporate) firewalls. The JW Player 5.3 :ref:`detects and circumvents this issue <rtmpt>`. 
    15  
    16 * RTMP is a *true* streaming protocol, which means that the bandwidth of the connection must always be larger than the datarate of the video. If the connection drops for just a few seconds, the stream will stutter. If the connection overall is just a little less than the video datarate, the video will not play at all. With :ref:`httpstreaming` on the other hand, people can simply wait until more of the video is downloaded. 
    17  
    18 The JW Player supports a wide array of features of the RTMP protocol. 
     10* Videos delivered over RTMP (and its encrypted brother, RTMPE) are harder to steal than videos delivered over regular HTTP. 
     11 
     12However, do note that RTMP has its disadvantages too. Especially since the introduction of :ref:`httpstreaming` (used by e.g. Youtube), RTMP is not the only option for efficient video delivery. Some drawbacks to be aware of: 
     13 
     14* RTMP is a different protocol than HTTP and is sent over a different port (1935 instead of 80). Therefore, RTMP is frequently blocked by (corporate) firewalls. The JW Player :ref:`detects and circumvents this issue <rtmpt>`. 
     15* RTMP is a *true* streaming protocol, which means that the bandwidth of the connection must always be larger than the datarate of the video. If the connection drops for a couple of seconds, the stream will stutter. If the connection bandwidth overall is smaller than the video datarate, the video will not play at all. 
     16 
     17The JW Player supports a wide array of features of the RTMP protocol, listed below. 
    1918 
    2019 
     
    2524 
    2625* The `Flash Media Server <http://www.adobe.com/products/flashmediaserver/>`_ from Adobe is the de facto standard. Since Flash is also developed by Adobe, new video functionalities always find their way in FMS first. 
    27 * The `Wowza Media Server <http://www.wowzamedia.com>`_ from Wowza is a great alternative, because it includes support for other streaming protocols than RTMP (for e.g. Shoutcast, the iPhone or Silverlight). 
    28 * The `Red5 Media Server <http://red5.org/>`_ is an open-source RTMP alternative. It lags in features (e.g. no dynamic streaming), but has an active and open community of developers. 
     26* The `Wowza Media Server <http://www.wowzamedia.com>`_ from Wowza is a great alternative, because it includes support for other streaming protocols than RTMP (for e.g. Shoutcast, the iPad/iPhone or Silverlight). 
     27* The `Red5 Media Server <http://red5.org/>`_ is an open-source RTMP alternative. It lags in features (e.g. no dynamic streaming), but is completely free. 
    2928 
    3029RTMP servers are not solely used for one-to-many media streaming. They include support for such functionalities as video conferencing, document sharing and multiplayer games. Each of these functionalities is separately set up on the server in what is called an *application*. Every application has its own URL (typically a subfolder of the root). For example, these might be the path to both an on-demand streaming and live streaming application on your webserver: 
     
    3433   rtmp://www.myserver.com/ondemand/ 
    3534   rtmp://www.myserver.com/live/ 
     35 
     36The JW Player solely supports the basic live, on-demand and dvr streaming applications. There's no support for such things as webcasting, videochat or screen sharing. 
    3637 
    3738 
     
    6566* For AAC audio: **file=mp4:song.aac** (with *mp4:* prefix). 
    6667 
    67 You do not have to do this with the JW Player, since the player takes care of stripping the extension or adding the prefix. If you do add the prefix yourself, the player will recognize it and not modify the URL. 
     68You do not have to do this with the JW Player, since the player takes care of stripping the extension and/or adding the prefix. If you do add the prefix yourself, the player will recognize it and not modify the URL. 
    6869 
    6970Additionally, the player will leave querystring variables (e.g. for certain CDN security mechanisms) untouched. It basically ignores everything after the **?** character. However, because of the way options are :ref:`loaded <options>` into Flash, it is not possible to plainly use querystring delimiters (*?*, *=*, *&*) inside the *file* or *streamer* option. This issue can be circumvented by :ref:`URL encoding these characters <options>`. 
     71 
     72.. note:: 
     73 
     74   Amazon Cloudfront's private streaming protocol is an example in which the MP4 URL should be URL Encoded, since the long security hash appended to the video URL can contain special characters. 
    7075 
    7176 
     
    159164^^^^^^^^^^^^^^^^^^ 
    160165 
    161 Flash Media Server 3.5, introduced DVR live streaming - the ability to pause and seek in a live stream. This functionality is supported by the JW Player. It can be enabled by setting the option **rtmp.dvr=true**. 
    162  
    163 By default, a DVR stream acts like a regular on-demand stream, the only difference being that the *duration* of the stream keeps increasing. This leads to a slightly awkward user experience, since the time scrubber in the controlbar keeps bouncing around in one position instead of moving to the right. 
    164  
    165 To solve this issue, also set the *duration* option to the total duration of your live event (or, to be safe, a few minutes longer). That way the time scrubber will function normally. The *live head* of the event is then indicated by the download progress bar in the player. If a user seeks beyond that point, he will automatically get pushed to that head. Here's an example of DVR Live Streaming with duration (3600 seconds is 1 hour): 
     166Flash Media Server 3.5 introduced live DVR streaming - the ability to pause and seek in a live stream. A DVR stream acts like a regular on-demand stream, the only difference being that the *duration* of the stream keeps increasing (that is, when the stream is still recording). 
     167 
     168Instead of starting from the beginning, the player will automatically jump to the *live* head of the DVR stream, so users can jump right into a live event. Subsequently, they are able to seek back to the beginning. 
     169 
     170In order to enable DVR streaming you should: 
     171 
     172* Install the **DVRCast** application (which is provided for free by Adobe) onto your FMS3.5 server. Certain Content Delivery Networks (like `Edgecast <http://edgecast.com/>`_) have this application already installed for you. 
     173* Use a live stream publishing tool (such as Adobe's Flash Media Live Encoder 3.1) that can issue DVR recording commands to an RTMP server. 
     174* Set the option **rtmp.dvr=true**. to your JW Player. This option switches the player in **DVRCast** mode, attempting to DVR subscribe to the stream and increasing the duration of the stream if recording is still in progress. 
     175 
     176Here is an example embed code, with the *rtmp.dvr* option set: 
    166177 
    167178.. code-block:: html 
     
    173184       file:'livepresentation', 
    174185       streamer:'rtmp://www.myserver.com/live/', 
    175        'rtmp.dvr':'true', 
    176        'duration':'3600' 
    177      }; 
    178  
    179      swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,  
    180       {allowfullscreen:'true',allowscriptaccess:'always'}, 
    181       {id:'jwplayer',name:'jwplayer'} 
    182      ); 
    183    </script> 
    184  
    185  
    186 .. note:: DVR Live Streaming only works in combination with Adobe's Live Media Encoder and an RTMP server that has DVR enabled. 
     186       'rtmp.dvr':'true' 
     187     }; 
     188 
     189     swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,  
     190      {allowfullscreen:'true',allowscriptaccess:'always'}, 
     191      {id:'jwplayer',name:'jwplayer'} 
     192     ); 
     193   </script> 
    187194 
    188195 
     
    190197----------------- 
    191198 
    192 Like with :ref:`httpstreaming`, RTMP Streaming includes the ability to dynamically optimize the video quality for each individual viewer. Adobe calls this mechanism *dynamic streaming*. This functionality is supported for FMS 3.5+ and Wowza 2.0+. 
    193  
    194 To use dynamic streaming, you need multiple copies of your MP4 or FLV video, each with a different quality (dimensions and bitrate). These multiple videos are loaded into the player using an mRSS playlist (see example below). The player recognizes the various *levels* of your video and automatically selects the highest quality one that: 
     199Like :ref:`httpstreaming`, RTMP Streaming includes the ability to dynamically optimize the video quality for each individual viewer. Adobe calls this mechanism *dynamic streaming*. This functionality is supported for FMS 3.5+ and Wowza 2.0+. 
     200 
     201To use dynamic streaming, you need multiple copies of your MP4 or FLV video, each with a different quality (dimensions and bitrate). These multiple videos are loaded into the player using an mRSS playlist (see example right below) or SMIL file (see :ref:`loadbalancing`) The player recognizes the various *levels* of your video and automatically selects the highest quality one that: 
    195202 
    196203* Fits the *bandwidth* of the server » client connection. 
    197204* Fits the *width* of the player's display (or, to be precise, is not more than 20% larger). 
     205* Results in less than 25% *frames dropped* at any point in time (e.g. 7fps for a video that is 25fps). 
    198206 
    199207As a viewer continues to watch the video, the player re-examines its decision (and might switch) in response to certain events: 
     
    201209* On a **bandwidth** increase or decrease - the bandwidth is re-calculated at an interval of 2 seconds. 
    202210* On a **resize** of the player. For example, when a viewer goes fullscreen and has sufficient bandwidth, the player might serve an HD version of the video. 
     211* On a **framedrop** of more than about 7 or 8 fps.  
     212 
     213Framedrop is continously monitored. Spikes are ruled out by taking 5-second averages. Once a quality level results in too large a framedrop, it will be *blacklisted* (made unavailable) for 30 seconds. After 30 seconds, it will be made available again, since the framedrop might be a result of a very decoding-heavy section in the video or external forces (e.g. the user opening Microsoft Office ;). 
    203214 
    204215Unlike with :ref:`httpstreaming`, a dynamic streaming switch is unobtrusive. There'll be no re-buffering or audible/visible hickup. It does take a few seconds for a switch to occur in response to a bandwidth change / player resize, since the server has to wait for a *keyframe* to do a smooth switch and the player always has a few seconds of the old stream in its buffer. To keep stream switches fast, make sure your videos are encoded with a small (2 to 4 seconds) keyframe interval. 
     
    206217.. note::  
    207218 
    208    So far, we have not been able to combine dynamic streaming with live streaming. This functionality is highlighted in  documentation from Adobe and Wowza, but in our tests we found that the bandwidth the player receives never exceeds the bandwidth of the level that currently plays. In other words: the player will never switch to a higher quality stream than the one it starts with. This seems to be a bug in the Flash plugin, since both FMS and Wowza have this issue. 
     219   So far, we have not been able to combine dynamic streaming with live streaming. This functionality is highlighted in  documentation from FMS, but in our tests we found that the bandwidth the player receives never exceeds the bandwidth of the level that currently plays. In other words: the player will never switch to a higher quality stream than the one it starts with. 
    209220 
    210221 
     
    246257 
    247258 
     259.. _loadbalancing: 
     260 
    248261Load Balancing 
    249262-------------- 
     
    252265 
    253266* The player first requests the XML file (typically from a single *master* server). 
    254 * The server returns the XML file, which includes the location of the RTMP server to use (typically the server that's least busy). 
     267* The server returns the XML file, which includes the location of the RTMP server to use (typically the server that's least busy) and the location of the videos on this server. 
    255268* The player parses the XML file, connects to the server and starts the stream. 
    256269 
     
    292305 
    293306 
    294  
    295307Playlists 
    296308^^^^^^^^^ 
     
    318330See the playlist section above for more information on format and element support. 
    319331 
    320 .. note::  
    321  
    322    A combination of load balancing + dynamic streaming is not possible yet. We are working on such a functionality, which will be included in a future version of the player. 
     332 
     333Dynamic Streaming 
     334^^^^^^^^^^^^^^^^^ 
     335 
     336The dynamic streaming mechanism of FMS 3.5+ and Wowza 2.0+ can be used in combination with load balancing. Therefore, simply add the different levels of your video to the SMIL file. Here's an example again: 
     337 
     338.. code-block:: html 
     339 
     340   <smil>  
     341     <head>  
     342       <meta base="rtmp://server1234.mycdn.com/ondemand/" />  
     343     </head>  
     344     <body>  
     345       <switch> 
     346         <video src="videos/Qvxp3Jnv-486.mp4" system-bitrate="1800000" width="1280" /> 
     347         <video src="videos/Qvxp3Jnv-485.mp4" system-bitrate="1100000" width="720"/>  
     348         <video src="videos/Qvxp3Jnv-484.mp4" system-bitrate="700000" width="480"/>  
     349         <video src="videos/Qvxp3Jnv-483.mp4" system-bitrate="400000" width="320"/>  
     350       </switch> 
     351     </body>  
     352   </smil> 
     353 
     354A couple of hints: 
     355 
     356* This file is structured, and behaves exactly the same as the one Adobe uses in its `dynamic streaming documentation <http://www.adobe.com/devnet/flashmediaserver/articles/dynstream_advanced_pt1.html>`_. The *width* attributes of the various bitrate levels are not required (though preferred) by the JW Player. 
     357* Opposed to a *regular* loadbalancing SMIL document, a dynamic streaming SMIL contains a *<switch>* statement directly inside the <body>* element. Include the closing *</switch>* as well! 
     358* Opposed to MediaRSS feeds, the bitrate attributes of the various levels are set in *bitspersecond*, **not** in *kilobitspersecond*. 
     359 
    323360 
    324361 
    325362.. _rtmpt: 
    326363 
    327 RTMP Tunnelling 
    328 --------------- 
     364RTMPT Fallback 
     365-------------- 
    329366 
    330367A frequent issue with RTMP streaming is the protocol being blocked by corporate firewalls. RTMP uses the UDP transmission protocol over port 1935, whereas regular HTTP traffic uses the TCP protocol over port 80. 
     
    335372 
    336373* First, the player connects to the regular application, either RTMP or RTMPe (encrypted). 
    337 * 500 milliseconds later, the player connects to the same application over a tunneled connection, either RTMPT or RTMPTe (tunnelled and encrypted). 
     374* Half a second later, the player connects to the same application over a tunneled connection, either RTMPT or RTMPTe (tunnelled and encrypted). 
    338375* Whichever connection is established first is used for streaming the video. 
    339376 
    340 In most cases the player is connected to the application over RTMP within 500 milliseconds, cancelling the second connection. This functionality is fully automated (no need to set port numbers or **t** in your *streamer* flashvar) and works for all flavors of RTMP streaming (on-demand, live, dvr and dynamic). 
     377In most cases the player is connected to the application over RTMP within 500 milliseconds, cancelling the second connection. This functionality is fully automated (no need to set port numbers or rtmp **t** in your *streamer* flashvar) and works for all flavors of RTMP streaming (on-demand, live, dvr and dynamic). 
  • trunk/fl5/doc/publishers/skinning.rst

    r1153 r1280  
    590590   :alt: Playlist Screenshot 
    591591 
     592.. note:: 
     593       
     594   When a playlist button is less than 240px wide and/or less than 40 pixels high, its image and description are automatically hidden, allowing for a *light* playlist to be displayed. 
    592595 
    593596Playlist XML Syntax 
  • trunk/fl5/src/com/longtailvideo/jwplayer/media/HTTPMediaProvider.as

    r1273 r1280  
    11/** 
    2  * Manages playback of http streaming flv. 
     2 * Manages playback of http streaming flv and mp4. 
    33 **/ 
    44package com.longtailvideo.jwplayer.media { 
     
    5656                /** Loaded amount for DVR streaming. **/ 
    5757                private var _dvrloaded:Number = 0; 
     58                /** Framerate of the video. **/ 
     59                private var _framerate:Number = 30; 
    5860                /** Number of frames dropped at present. **/ 
    5961                private var _droppedFrames:Array; 
     
    139141                                var drp:Number = (_droppedFrames[len-1] - _droppedFrames[len-6])/5; 
    140142                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: {droppedFrames:drp}}); 
    141                                 if(drp > 7 && item.currentLevel < item.levels.length - 1) { 
     143                                if(drp > _framerate/4 && item.currentLevel < item.levels.length - 1) { 
    142144                                        item.blacklistLevel(item.currentLevel); 
    143145                                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: {type:'blacklist',level:item.currentLevel}}); 
     
    225227                        _bufferFull = false; 
    226228                        _bufferingComplete = false; 
    227                         _bandwidthSwitch = true; 
    228229                         
    229230                        if (item.levels.length > 0) { item.setLevel(item.getLevel(config.bandwidth, config.width)); } 
     
    249250                                _video.height = dat.height; 
    250251                                resize(_width, _height); 
     252                        } 
     253                        if(dat.videoframerate) {  
     254                                _framerate = Number(dat.videoframerate); 
    251255                        } 
    252256                        if (dat['duration'] && item.duration <= 0) { 
     
    431435                        _droppedFrames = new Array(); 
    432436                        _keyframes = undefined; 
     437                        _framerate = 30; 
     438                        _bandwidthSwitch = true; 
    433439                        _bandwidthChecked = false; 
    434440                        _meta = false; 
  • trunk/fl5/src/com/longtailvideo/jwplayer/media/RTMPMediaProvider.as

    r1268 r1280  
    11/** 
    22 * Wrapper for playback of _video streamed over RTMP. 
    3  * 
    4  * All playback functionalities are cross-server (FMS, Wowza, Red5) 
    53 **/ 
    64package com.longtailvideo.jwplayer.media { 
     
    8886                        _connections = new Array(); 
    8987            var untunneled:NetConnection = new NetConnection(); 
    90             untunneled.addEventListener(NetStatusEvent.NET_STATUS, statusHandler); 
    9188            untunneled.objectEncoding = ObjectEncoding.AMF0; 
    9289            untunneled.client = new NetClient(this); 
     
    9491            var tunneled:NetConnection = new NetConnection(); 
    9592            tunneled = new NetConnection(); 
    96             tunneled.addEventListener(NetStatusEvent.NET_STATUS, statusHandler); 
    9793            tunneled.objectEncoding = ObjectEncoding.AMF0; 
    9894            tunneled.client = new NetClient(this); 
     
    508504                        _stream.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); 
    509505                        _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler); 
    510                         if(getConfigProperty('dvr')) { 
    511                                 _stream.bufferTime = 5; 
     506                        if(getConfigProperty('dvr') || getConfigProperty('subscribe')) { 
     507                                _stream.bufferTime = 3; 
    512508                        } else {  
    513509                                _stream.bufferTime = config.bufferlength; 
     
    535531                        _connections[_connection].addEventListener(IOErrorEvent.IO_ERROR, errorHandler); 
    536532                        _connections[_connection].addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler); 
     533                        _connections[_connection].addEventListener(NetStatusEvent.NET_STATUS, statusHandler); 
    537534                        clearTimeout(_connectionTimeout); 
    538535                    } else { 
  • trunk/fl5/src/com/longtailvideo/jwplayer/model/PlayerConfig.as

    r1246 r1280  
    2121                protected var _autostart:Boolean        = false;  
    2222                protected var _bandwidth:Number         = 1500; 
    23                 protected var _bufferlength:Number      = 1;  
     23                protected var _bufferlength:Number      = 2;  
    2424                protected var _displaytitle:Boolean = true;  
    2525                protected var _fullscreen:Boolean       = false; 
  • trunk/fl5/src/com/longtailvideo/jwplayer/player/PlayerVersion.as

    r1273 r1280  
    33         
    44        public class PlayerVersion { 
    5                 protected static var _version:String = "5.3.1273"; 
     5                protected static var _version:String = "5.3.1279"; 
    66                 
    77                public static function get version():String { 
  • trunk/fl5/src/com/longtailvideo/jwplayer/view/components/PlaylistComponent.as

    r1270 r1280  
    269269                        var title:TextField = new TextField(); 
    270270                        title.name = "title"; 
    271                         //title.autoSize = TextFieldAutoSize.LEFT; 
    272271                        title.defaultTextFormat = titleTextFormat; 
    273272                        title.wordWrap = true; 
    274273                        title.multiline = true;  
    275                         title.width = 315; 
     274                        title.width = 300; 
    276275                        title.height = 20; 
    277                         addElement(title, btn, img.width + imageOffset, 2);      
     276                        addElement(title, btn, img.width + imageOffset, 3); 
    278277                                 
    279278                        var descriptionTextFormat:TextFormat = new TextFormat(); 
    280                         descriptionTextFormat.size = fontSize ? fontSize : 11; 
     279                        descriptionTextFormat.size = fontSize ? fontSize - 2 : 11; 
     280                        descriptionTextFormat.leading = 1; 
    281281                        descriptionTextFormat.font = fontFace ? fontFace : "_sans"; 
    282282                        descriptionTextFormat.bold = (fontWeight == "bold"); 
     
    284284                        var description:TextField = new TextField(); 
    285285                        description.name = "description"; 
    286                         //description.autoSize = TextFieldAutoSize.LEFT; 
    287286                        description.wordWrap = true; 
    288287                        description.multiline = true; 
    289                         description.width = 340; 
    290                         description.height = back.height - 20; 
     288                        description.width = 335; 
     289                        description.height = back.height - 22; 
    291290                        description.defaultTextFormat = descriptionTextFormat; 
    292                         addElement(description, btn, img.width + imageOffset + 1, 20); 
     291                        if(back.height > 40) { 
     292                                addElement(description, btn, img.width + imageOffset + 1, 22); 
     293                        } 
    293294                         
    294295                        var duration:TextField = new TextField(); 
     
    296297                        duration.width = 40; 
    297298                        duration.height = 20; 
    298                         titleTextFormat.size = fontSize ? fontSize : 11; 
    299299                        titleTextFormat.align = TextFormatAlign.RIGHT; 
     300                        titleTextFormat.size = fontSize ? fontSize - 1 : 11; 
     301                        titleTextFormat.rightMargin = 5; 
    300302                        duration.defaultTextFormat = titleTextFormat; 
    301                         addElement(duration, btn, title.x + title.width - 20, 4); 
     303                        addElement(duration, btn, title.x + title.width - 2, 4); 
    302304                         
    303305                        back.width = btn.width; 
     
    387389                                                }  
    388390                                        } else if (overClip) { 
    389                                                 outClip.visible = (idx != active); 
    390391                                                overClip.visible = false; 
    391                                                 if (activeClip) activeClip.visible = (idx == active); 
     392                                                if (activeClip) { 
     393                                                        outClip.visible = (idx != active); 
     394                                                        activeClip.visible = (idx == active); 
     395                                                } else { 
     396                                                        outClip.visible = true; 
     397                                                } 
    392398                                        } 
    393399                                } 
     
    544550                        if (playlistItem.image || playlistItem['playlist.image']) { 
    545551                                var imageFile:String = playlistItem['playlist.image'] ? playlistItem['playlist.image'] : playlistItem.image; 
    546                                 if (getConfigParam('thumbs') != false && _player.config.playlist != 'none') { 
     552                                if (getConfigParam('thumbs') != false && _player.config.playlist != 'none' && buttonheight > 39 && getConfigParam("width") > 239) { 
    547553                                        var img:Sprite = getButton(idx).getChildByName("image") as Sprite; 
    548554                                        if (img) { 
     
    558564                        if (duration && playlistItem.duration) { 
    559565                                if (playlistItem.duration > 0) { 
    560                                         duration.text = Strings.digits(playlistItem.duration); 
     566                                        duration.htmlText = "<b>" + Strings.digits(playlistItem.duration) + "</b>"; 
    561567                                        if (fontColor) { 
    562568                                                duration.textColor = fontColor.color; 
     
    595601                        } 
    596602                        img = getButton(idx).getChildByName("image") as MovieClip; 
    597                         if (img && (!(playlistItem.image || playlistItem['playlist.image']) || getConfigParam('thumbs') == false)) { 
     603                        if (img && (!(playlistItem.image || playlistItem['playlist.image']) || getConfigParam('thumbs') == false || buttonheight < 40 || getConfigParam("width") < 240)) { 
    598604                                if (!img.getChildByName("imageBackground")) { 
    599605                                        getButton(idx).getChildByName("image").visible = false; 
Note: See TracChangeset for help on using the changeset viewer.