13 December 2010
Page tools |
Familiarity with ActionScript 3 and Adobe Flash Builder.
Advanced
With the release of Flash Player 10, Adobe introduced Real-Time Media Flow Protocol (RTMFP). When used for real-time collaboration applications, RTMFP provides several advantages when compared to Real-Time Messaging Protocol (RTMP)—most notably, reduced latency and direct peer-to-peer connections.
To use RTMFP, however, Flash Player needs to connect to a real-time communications service such as that provided by Adobe Flash Media Server 4 or Codename Cirrus. The Cirrus service (rtmfp://p2p.rtmfp.net), hosted by Adobe, can be used for development purposes. You can view it as a stripped-down version of Flash Media Server (FMS) 4 that exclusively provides a rendezvous service: it does not support media relay, shared objects, remote method invocation, or other features of Flash Media Server 4.
To deploy commercial applications using RTMFP, you must use Flash Media Server 4. Not only can you take advantages of all FMS capabilities, but you can address firewall-related limitations of the Cirrus service that would prevent successful deployment of your application.
In this article, I first point out the advantages of RTMFP versus RTMP. I then describe the challenges faced by RTMFP. Next, I provide solutions for these challenges using Flash Media Server. Finally, I present a sample video meeting application demonstrating how to seamlessly work around different versions of Flash Player instances and network firewall devices.
This article is intended for intermediate and advanced ActionScript developers. It does not explain how to create basic streaming applications, but focuses on more advanced topics. For an introduction and API review of RTMFP, please read Cirrus service for developing end-to-end applications using RTMFP in Flash Player 10.
Adobe LiveCycle Collaboration Services (LCCS) is a high-level SDK that takes care of all the issues discussed here. This article is intended for developers who would like to get more control than that provided by LCCS.
With the release of Flash Player 10.1 and Flash Media Server 4, RTMFP further provides application-level and native IP multicast. These capabilities of RTMFP are out of the scope of the article.
RTMP is an open protocol introduced in Flash Player 6 that mainly targets streaming audio and video content. Over time, several flavors of RTMP were developed, including tunneling over HTTP, providing protected content, and more. RTMP is based on Transmission Control Protocol (TCP). As such, it provides reliable data delivery between Flash Media Server and Flash Player, which is achieved at the price of unbounded delay. This is not a problem for broadcast-type media distribution (either live or recorded) because Flash Player maintains a playback buffer—typically several seconds long—that can compensate for network interruptions. In these applications, ensuring media integrity is of higher importance than timely delivery. Losing media data could also introduce undesirable audio/video distortion.
Flash Player 10 (and Adobe AIR 1.5) introduced RTMFP. Unlike RTMP, RTMFP is based on User Datagram Protocol (UDP). UDP provides fast and unreliable data delivery with minimal overhead; there is no flow control, congestion control, or other safeguards. UDP is popularly used for real-time communications applications where minimizing delay between communicating endpoints is of utmost importance. In addition, UDP also facilitates direct media exchange between communicating endpoints, which not only further reduces delay between endpoints, but also reduces media relay server requirements.
In real-time collaboration applications, minimizing delay is one of the most important goals; a few hundred milliseconds' worth of delay could render a conversation unusable. Achieving reliable transmission may not be needed since modern audio and video coding technologies (such as the Speex voice codec and the H.264 video codec, both available in Flash Player) are designed to deal with network transmission errors and thus provide error concealment techniques.
When compared to RTMP, RTMFP provides the following advantages for real-time collaborations applications:
To use Real-Time Media Flow Protocol (RTMFP), Flash Player needs to connect to a service (either the hosted Cirrus service or Flash Media Server). This is required to obtain a so-called peer identifier, a unique 256-bit random number that is used in establishing communications between peers.
When creating commercial applications, developers must address the following issues:
The following section reviews in detail how you can address each of these challenges by using Flash Media Server.
Flash Media Server (FMS) 4 can be used to build applications using all the advantages of RTMFP. In addition, one can take advantage of all existing features such as shared objects and remote method invocation (RMI).
The following subsections describe how to address each of the challenges of RTMFP described in the previous section, providing ActionScript source code for both client and server where applicable.
While rarely the case with small office or home office (SOHO) firewalls, it is quite common for corporate firewalls to block UDP traffic altogether. One solution is to configure Flash Player to use a TURN proxy (Traversal Using Relays around NAT). As documented in the Adobe Flash Player 10.1 Administration Guide, Flash Player can be configured to support IETF Internet Draft "draft-ietf-behave-turn-08" without authentication by specifying the following option in mms.cfg:
RTMFPTURNProxy = ip_address_or_hostname_of_TURN_proxy
This solution requires your corporate IT department to develop and deploy a conforming TURN proxy.
A more desirable solution is to seamlessly fail over to an RTMP connection when an RTMFP connection to the server cannot be established. Unfortunately, there is no way to probe whether an RTMFP connection to the server will be successful. The only way is to attempt the connection and wait for a NetConnection.Connect.Success
or NetConnection.Connect.Failed
response. A failed connection will provide a NetConnection.Connect.Failed
event after a 90-second timeout. One approach would be to try parallel connections of both RTMP and RTMFP to the server. Whenever RTMFP succeeds, the RTMP connection can simply be closed.
Another strategy is to try protocols sequentially in preference order (for instance, RTMFP, RTMP, RTMPT) with a given timeout. This sample client-side ActionScript code demonstrates sequential connection establishment:
private var rtmfpTimer:Timer = null; private var netConnection:NetConnection = null; private const ConnectionTimeout:int = 5000; public function register(rtmp:Boolean):void { netConnection = new NetConnection(); netConnection.addEventListener(NetStatusEvent.NET_STATUS, connectionHandler); netConnection.connect(rtmp ? "rtmp:" : "rtmfp:" + "//server.domain/application"); if (!rtmp) { rtmfpTimer = new Timer(ConnectionTimeout, 1); rtmfpTimer.addEventListener(TimerEvent.TIMER_COMPLETE, rtmfpTimeoutHandler); rtmfpTimer.start(); } } private function rtmfpTimeoutHandler(e:TimerEvent):void { netConnection.close(); netConnection = null; register(true); } private function connectionHandler(e:NetStatusEvent):void { if (rtmfpTimer) { rtmfpTimer.stop(); rtmfpTimer = null; } if ("NetConnection.Connect.Success" == e.info.code) { // RTMFP or RTMP connection succeeded } else if ("NetConnection.Connect.Failed" == e.info.code) { // RTMFP or RTMP connection failed } }
It is quite possible that not all Flash Player endpoints can use RTMFP. For instance:
In both of these cases, the only solution is to send media through Flash Media Server. FMS will transparently bind RTMPx and RTMFP streams together: no server or client work is needed.
Since RTMP only works in a client-server scenario, your application is responsible for switching its conference topology between direct communications and client-server communications. Assume that there are two participants (say, A and B) in a video meeting using direct communications over RTMFP. When client C (using RTMP) joins, the meeting topology must be converted to client-server; that is, all media must go through the central FMS. When client C leaves, the meeting can be converted back to a direct connection. Note that clients A and B do not need to change protocol from RTMFP to RTMP; FMS will perform seamless bridging of the two protocols.
Even if both Flash Player endpoints successfully connect to the RTMFP service, there is no guarantee that two clients can communicate directly with each other because intermediaries such as firewalls can block communications between two endpoints. RFC 3489, STUN—Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators—classified network address translators (NATs) into the following four categories: full cone, restricted cone, port restricted cone, and symmetric. (Full cone is the most permissive and symmetric is the most restrictive.) Later experimentation has found that firewalls cannot be clearly classified to the above categories; for instance, certain firewalls exhibit different behavior for incoming and outgoing traffic.
Although you can predict whether direct communications between two endpoints will be successful by knowing the firewall types, no guarantees can be given. The best way to see whether direct communication between two endpoints is possible is simply to try. This is the approach adopted by RFC 5245, Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols. First, a series of communication addresses are collected. These addresses include local addresses, external addresses, or relayed addresses. Communications starts with the address with the highest probability of success (which may not be the cheapest solution) and later changing to the cheapest possible solution (local address).
In this example, I've adopted a similar solution. To start, the application sends media both through the server and directly to peers. Sending media through FMS always succeeds. An alternative approach would be to simply probe using data messages to see whether direct connection between two clients is available. There are two ways to detect whether a direct connection was successful:
NetStream.Play.Start
on an incoming directly connected stream onPeerConnect()
callback on the NetStream
client object on an outgoing directly connected stream This following sample code demonstrates the idea. Here's the code for the publishing client:
private var outgoingStreamDirect:NetStream = null; private var outgoingStreamFms:NetStream = null; private function multiPublish():void { outgoingStreamDirect = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS); outgoingStreamFms = new NetStream(netConnection); outgoingStreamDirect.publish("streamDirect"); var c:Object = new Object(); c.onPeerConnect = function(peer:NetStream):Boolean { // if we receive onPeerConnect, it means that direct connection succeeded if (outgoingStreamFms) { outgoingStreamFms.close(); outgoingStreamFms = null; } return true; } outgoingStreamDirect.client = c; outgoingStreamFms.publish("streamFms") }
In the subscribing client, it is assumed that the publishing peer ID is already known:
private var incomingStreamDirect:NetStream = null; private var incomingStreamFms:NetStream = null; private function multiSubscribe():void { incomingStreamFms = new NetStream(netConnection); incomingStreamDirect = new NetStream(netConnection, id_of_publishing_client); incomingStreamDirect.addEventListener(NetStatusEvent.NET_STATUS, streamHandler); incomingStreamFms.play("streamFms"); incomingStreamDirect.play("streamDirect"); } private function streamHandler(e:NetStatusEvent):void { // if Play.Start event received on direct connection, it means that direct communications is possible if ("NetStream.Play.Start" == e.info.code) { if (incomingStreamFms) { incomingStreamFms.close(); incomingStreamFms = null; } } }
You have several strategies to choose from for when to start sending and receiving media. You may want to start sending and receiving media right away using the client-server stream, since that will succeed in every case. There may be a small glitch, however, when switching over from client-server to direct connections. Alternatively, you may want to wait to start with a direct connection and failover to client-server after a given timeout.
Direct connections are preferred between communicating clients to minimize latency and reduce server costs. In a multiparty session, each participating client must send media to all participating clients (see Figure 1). Thus, each client uses the same uplink and downlink bandwidth. Assuming each media stream requires b bandwidth, the required uplink or downlink bitrate is b (n–1), where n is the number of participating clients. This is a poor match for home users' cable or ADSL modems. Imagine a 500 Kbps video stream, even a few participants may easily overwhelm one's uplink, causing performance degradation. On the other hand, client-server topology is a perfect match for asymmetric network connections. It requires b uplink bandwidth and b (n–1) downlink.
RTMFP assigns a peer ID to each participant. These peer IDs are 256 bits long and are non-forgeable. When you want to subscribe to a directly published stream, you must specify the publisher's peer ID:
var receiveStream:NetStream = new NetStream(netConnection, id_of_publishing_client); receiveStream.play("media");
Therefore, your application needs to provide some kind of service to exchange peer IDs. You can use XMPP or a web service to exchange peer IDs. FMS offers remote procedure calls or remote shared objects to perform this task. The following example demonstrates how to exchange peer IDs using remote method invocation.
Here is the FMS Server-Side ActionScript (SSAS):
application.onConnect = function(client, userName) { client.userName = userName; // server-side functions client.getRemoteId = getRemoteId; application.acceptConnection(client); return true; } function findUser(userName) { for (var i = 0; i <= application.clients.length; i++) { if (application.clients[i].userName == userName) { return i; } } return -1; } function getRemoteId(userName) { var result = new Object; result.userName = userName; result.id = ""; result.protocol = ""; var index = findUser(userName); if (-1 != index) { result.id = application.clients[index].farID; result.protocol = application.clients[index].protocol; } return result; }
Here is the Flash Player code to register and look up the peer ID:
private var netConnection:NetConection = null; private function connect():void { netConnection = new NetConnection(); netConnection.connect("rtmfp://example.com/app", "user"); } private function lookup(remoteUser:String):void { var responder:Responder = new Responder(userResult); netConnection.call("getRemoteId", responder, remoteUser); } private function userResult(result:Object):void { // process respons // result.id; // result.userName; // result.protocol; }
I have developed a sample application demonstrating the following items discussed in this article:
The application was developed using Flash Builder 4. The minimum requirement is Flash Player 10; it does not handle Flash Player 9 gracefully (an update is required using Express Install). The application requires Flash Media Server 4. In order to minimize latency for real-time collaboration applications, disable Aggregate Messages and Queuing (by disabling AggregateMessages in Vhost.xml, Queue and AggregateMessages in Application.xml); see also Send aggregate messages in the Flash Media Server online documentation.
The following files are included:
NetStream
object. NetStream
object and corresponding Video
display object. This article presented several aspects of developing real-time collaboration applications. After this article, you should have a good understanding on how to make the best use of RTMFP with Flash Media Server in your real-time communications apps.
Here are some resources to help you develop real-time communications apps for Flash Media Server and Flash Player clients:
This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 Unported License.
Tutorials & Samples |
Flash Media Server Forum |
More |
05/07/2012 | Flash on Google Chrome |
---|---|
05/08/2012 | Republishing the Streams |
05/08/2012 | Publish multi-bitrate stream from FMS? |
05/07/2012 | How to change play video immediately ? |