By  David Hassoun
 
By  John Crosby
 
Created
23 June 2010
 

Requirements

 
Prerequisite knowledge

Basic knowledge of ActionScript 3 and Adobe Flash Builder or Adobe Flash Professional is recommended for this tutorial.
 

 
User level

Intermediate
 

 
Required products

 
Sample files

The RealEyes OSMF Player Sample (REOPS) is a project developed by RealEyes Media to provide the community a sample and an optional starting point for a robust video player utilizing the Open Source Media Framework (OSMF) from Adobe. The REOPS project is meant to be a building block for developers, as well as a visual representation to illustrate the capabilities of the OSMF framework and a "how to" for using it.
 
This article is a follow-up of our previous article, Part 1: Setup and deployment, where we introduced you to the REOPS project. In this article we show you how to build a very simple OSMF player to get familiar with the building blocks of the OSMF. We then explain each of these OSMF building blocks in simple terms, as well as how the REOPS project integrates each of them.
 

 
Building a simple player with the OSMF

In this walkthrough you will build a simple player using the OSMF to see these objects in action. For now, don't worry about the details of each item. We will review each of the objects, what they do, and how the REOPS uses them.
 
 
The REOPS Project
We will be referencing the REOPS project throughout this article, so if you haven't downloaded or checked out the REOPS code, you can do so from the Google code page:
 
 
The OSMF building blocks
We will also be reviewing the OSMF code, so you will want to download that as well. The REOPS project comes with the OSMF.swc file, but you may want to look at the actual OSMF framework code for yourself.
 
You can get the code in a couple of ways:
 
Before we dive into the code, we'll review some of the basic OSMF media player building blocks. That way you'll be familiar with them when you build a player, as well as when we review how the REOPS uses the OSMF to create powerful and flexible player platform.
 
To build a basic player, you need four things:
 
  • MediaElement: This object represents a specific piece of media: an image, a video,, or other media asset.
  • MediaPlayer: This is a high-level class that provides much of the plumbing necessary to interact with all media types.
  • MediaContainer: This is a Sprite-based container for media objects.
  • DisplayList: This is the display list of a Sprite that to which the MediaContainer object will be added.
Note: Completed files for this example can be found in the REOPS Google Code project downloads list. Look for TheSimplestPlayer.zip as a Flex project archive.
 
  1. Create a new Flash Builder ActionScript (Flex SDK 4) project named TheSimplestPlayer (see Figure 1).
Creating the new ActionScript project
Figure 1. Creating the new ActionScript project
  1. Add a SWC folder to the project named libs (see Figure 2).
Adding the SWC folder
Figure 2. Adding the SWC folder
  1. Once you complete the New Project Wizard, create the libs directory in the project. The new project should look something like Figure 3.
Reviewing the folder structure for TheSimplestPlayer
Figure 3. Reviewing the folder structure for TheSimplestPlayer
  1. Copy the OSMF SWC file from the code you should have downloaded from the OSMF site into the libs directory.
  2. Open TheSimplestPlayer.as in the default package.
  3. Add the following metadata just above the class declaration to set the width and height of the compiled SWF file:
[SWF( width="640", height="360" )] public class TheSimplestPlayer extends Sprite { }
  1. Inside the class constructor, create a variable named videoPath and type this variable as a String. Set this variable equal to the URL:
"rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short". This will be the media played. The OSMF manages splitting up the connection portion of the string from the content portion for streaming media:
 
public class TheSimplestPlayer extends Sprite { var videoPath:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short"; }
  1. Under the videoPath variable, create a new variable named resource and type resource as a URLResource object. Pass the videoPath variable you just created as the only parameter to the new URLResource object. This wraps the media path in a resource to be used at the context reference for a media element:
var videoPath:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short"; var resource:URLResource = new URLResource( videoPath );
  1. Create a new variable named element and type it as a VideoElement object. Pass the resource variable as the only parameter to the new VideoElement object. This creates a usable media element with all the needed connection and content pointer information for playback:
var resource:URLResource = new URLResource( videoPath ); var element:VideoElement = new VideoElement( resource );
  1. Create a mediaPlayer variable typed as a MediaPlayer object. Pass the element variable as the only parameter to the new MediaPlayer object. This creates the manager and controller for the media playback and sets the media to be loaded and played:
var element:VideoElement = new VideoElement( resource ); var mediaPlayer:MediaPlayer = new MediaPlayer( element );
  1. Create a new mediaContainer variable typed as a MediaContainer object. The MediaContainer will be the manager for the actual display of the media:
var mediaPlayer:MediaPlayer = new MediaPlayer( element ); var mediaContainer:MediaContainer = new MediaContainer();
  1. Call the addMediaElement() method on the mediaContainer object and pass it the element variable. This adds the actual media element to a display object:
var mediaContainer:MediaContainer = new MediaContainer(); mediaContainer.addMediaElement( element );
  1. Call the addChild() method and pass it the mediaContainer variable. This simply displays the MediaContainer to the display list:
mediaContainer.addMediaElement( element ); addChild( mediaContainer );
The completed code should look similar to the following:
 
[SWF( width="640", height="360" )] public class TheSimplestPlayer extends Sprite { public function TheSimplestPlayer() { var videoPath:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short"; var resource:URLResource = new URLResource( videoPath ); var element:VideoElement = new VideoElement( resource ); var mediaPlayer:MediaPlayer = new MediaPlayer( element ); var mediaContainer:MediaContainer = new MediaContainer(); mediaContainer.addMediaElement( element ); addChild( mediaContainer ); }
  1. Save the file and run the application. You should see the video play as in Figure 4.
Playing the video
Figure 4. Playing the video
This is a very simple player: there are no controls and it only plays a single video file—no playlist or other media types. However, this player does illustrate some of the core concepts of working with the OSMF.
 

 
How the REOPS player is built with the OSMF

The REOPS player uses the MediaPlayerSprite class. The MediaPlayerSprite class provides some out-of-the-box implementations that make developing with the OSMF much easier and quicker. The following sections will describe each of the main objects used to build an OSMF player and point out where the REOPS project integrates each of them. Figure 5 shows the general relationship of the objects used to build the REOPS using the OSMF.
 
Architecture of the REOPS player
Figure 5. Architecture of the REOPS player
 
The MediaPlayerSprite class
The MediaPlayerSprite (Figure 6) enables a MediaElement with a DisplayObjectTrait to be placed on the display list using the MediaContainer class. The MediaContainer class implements much of the necessary code to accomplish this task. Additionally, the MediaContainer class offers support for the OSMF internal layout API. Currently, the REOPS project doesn't use the MediaPlayerSprite, but rather uses the MediaContainer object directly. The MediaPlayerSprite creates the MediaContainer object for you.
 
Additionally, the MediaPlayerSprite class can handle the creation of a MediaPlayer controller class (you can also create your own MediaPlayer instance and pass it to the MediaPlayerSprite). MediaElement and MediaPlayer should sound familiar. They were both used in the example player that you just built. DisplayObjectTrait, however, is a new concept. Next, we'll show you where traits fit into the OSMF and the REOPS project.
 
 
Getting to know media traits
MediaElements, which we will cover in a moment, express their capabilities through traits. For example, an audio file has a duration or a timeline, but an image does not—so, an audio-based MediaElement object will have a TimeTrait where the image-based MediaElement will not.
 
Here are a few things to keep in mind when working with traits:
 
  • MediaElement can aggregate traits, so the audio-based MediaElement from before not only has a TimeTrait, but has an AudioTrait and a LoadTrait, among other traits.
  • Traits are independent of each other. One does not extend the other.
  • Traits dispatch their own events.
  • Traits can be added or removed at any time; so, you will need to listen for the traitAdd (MediaElementEvent.TRAIT_ADD) and traitRemove (MediaElementEvent.TRAIT_REMOVE) events on MediaElement objects to manage the capabilities of your media player to match those of the current MediaElement.
It can be quite a bit of work to get a player integrated with all the possible traits and combinations of traits that different MediaElements might have. Luckily, there is a class to help simplify the process of working with traits: the MediaPlayer class.
 

 
Introducing the MediaPlayer class

MediaPlayer is a high-level class that abstracts some of the lower level details of the OSMF. Instead of having to manage traits dynamically for all the different media types, the MediaPlayer class provides simple properties, methods, and events to handle all the normal trait management for you. The MediaPlayer class provides some default capabilities such as looping, auto-play and auto-rewind, as well as handling playback of any media type supported by the OSMF. This makes MediaPlayer a good base for a player.
 
The REOPS uses the MediaPlayer class directly (see Figure 6). For other use cases, MediaPlayerSprite creates an instance of the MediaPlayer class and applications can access the mediaPlayer instance variable to control the MediaElements.
 
The MediaPlayer class packaged within MediaPlayerSprite
Figure 6. The MediaPlayer class packaged within MediaPlayerSprite

 
Working with the MediaElements class

The MediaElement class and its subclasses represent the media items presented by the media player. MediaElements can represent a single piece of media, such as a video clip or an image, but may also represent a complex composition of media items. In TheSimplestPlayer example, there was only one MediaElement—a video clip, which used the VideoElement directly. This is fine to get the job done, but lacks flexibility. In order to handle multiple types of MediaElement—video, audio, images, compositions, and more—you would need to evaluate the type of media that you want to play, then create the correct MediaElement subclass. The OSMF provides you with the MediaFactory to accomplish this task.
 
 
Understanding the MediaFactory class
The MediaFactory class is what turns a URL or path into a MediaElement that the OSMF understands. The MediaFactory class maps resources’ paths to specific MediaElements by comparing each resource to a list of known resource types and their MediaElements. When a match is found, a MediaElement is created. The OSMF provides the DefaultMediaFactory, which can create MediaElements for all of the current media types supported by the OSMF.
 
Note: Reviewing the code in the org.osmf.media.MediaFactory and org.osmf.DefaultMediaFactory classes will give you a good base knowledge of how the MediaFactory works and how you can adjust the media types for your player.
 
Working with a MediaFactory is relatively straightforward. Once you've instantiated a MediaFactory object, you can call the createMediaElement() method, passing a MediaResource. The MediaFactory creates the appropriate MediaElement for that resource and returns that MediaElement back to the caller, where it can be applied to the player for display. The MediaFactory is meant to be extended and customized, but for most uses, you can use the DefaultMediaFactory class which provides the default media element creation functionality.
 
 
MediaElements and their resources
MediaElements are created based on the type of resource that needs to be presented. The MediaResourceBase class is the base class for all of these resources. Subclasses of MediaElementBase are specific to the type of media item. Here are some examples:
 
  • URLResource: Images, SWFs, progressive video
  • StreamingURLResource: Streaming video/audio
  • DynamicStreamingResource: Dynamic streaming video
The following code snippet shows a simple case using the MediaFactory:
 
var mediaFactory:MediaFactory = new DefaultMediaFactory(); var resource:MediaResourceBase = new URLResource( "http://path/to/media.mp3" ); var audioElement:AudioElement = mediaFactory.createMediaElement( resource );

 
Adding the MediaFactory to TheSimplestPlayer

In this simple walkthrough you will add the MediaFactory class to the code you created in the previous walkthrough to create MediaElements dynamically for you:
 
  1. Open TheSimplestPlayer.as in the default package from the previous code walkthrough.
  2. In the constructor method, under the line that creates the resource variable, create a new variable named mediaFactory, type it as a DefaultMediaFactory and set it equal to a new instance of DefaultMediaFactory:
var resource:URLResource = new URLResource( videoPath ); var mediaFactory:DefaultMediaFactory = new DefaultMediaFactory();
  1. Change the line that creates the element variable. Type the variable as a MediaElement and set it equal to the result of the createMediaElement() method. Make sure you pass the resource variable to the createMediaElement() method. Change this:
var element:VideoElement = new VideoElement( resource );
to this:
 
var element:MediaElement = mediaFactory.createMediaElement( resource );
The completed code should look similar to the following:
 
[SWF( width="640", height="360" )] public class TheSimplestPlayer extends Sprite { public function TheSimplestPlayer() { var videoPath:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short"; var resource:URLResource = new URLResource( videoPath ); var mediaFactory:DefaultMediaFactory = new DefaultMediaFactory(); var element:MediaElement = mediaFactory.createMediaElement( resource ); var mediaPlayer:MediaPlayer = new MediaPlayer( element ); var mediaContainer:MediaContainer = new MediaContainer(); mediaContainer.addMediaElement( element ); addChild( mediaContainer ); } }
  1. Save the file and run the application.
There should be no change, but you should now understand that with a few changes the player has become more flexible. You no longer need to know the type of MediaElement ahead of time. All you need to do is pass the MediaFactory a path to a piece of media. Then the MediaFactory figures out what type of MediaElement to create for you.
 
 
REOPS and the MediaFactory class
The REOPS project uses a custom REMediaFactory that extends MediaFactory to enable it to provide some advanced capabilities that will be covered in future articles (see Figure 7). The REOPS also implements connection sharing using a built in feature of the OSMF.
 
MediaFactory's place in the REOPS architecture
Figure 7. MediaFactory's place in the REOPS architecture
 
Connection sharing and the NetConnectionFactory
The REOPS project uses the NetConnectionFactory to implement connection sharing in the player (see Figure 8). The REMediaFactory constructor method can receive a NetConnectionFactory object as a parameter. The NetConnectionFactory can be used to generate NetConnection instances and manage connection sharing between MediaElements. It does this by comparing the URLs resource of MediaElements to determine what connections can be shared.
 
NetConnectionFactory's place in the REOPS architecture
Figure 8. NetConnectionFactory's place in the REOPS architecture
The following code snippet shows how simple it is to use the NetConnection manager to enable connection sharing in a player:
 
var netConnectionFactory:NetConnectionFactory = new NetConnectionFactory(); var mediaFactory:REMediaFactory = new REMediaFactory( netConnectionFactory );

 
Configuring a new REOPS player

You should have a good idea of the major components in an OSMF player and how the REOPS player is built using the OSMF. In this section we're going to show you how to set up the REOPS player via XML configuration and then deploy the player with the new configuration.
 
 
Setting up the REOPS XML configuration
A Flex project archive file has been provided as a starting point for this walkthrough. It can be found in the REOPS Google Code project downloads list; the archive is called MyREOPS_start.zip. The project includes a few things to make it quick and easy to get a REOPS player up and running:
 
  • src/MyREOPS.as: The main application file. There isn't much code because the class extends the REOPS class from the library.
  • libs/REOPSLib.swc: A SWC file of the REOPS project code (this can also be downloaded on the Google code project downloads list)
  • assets/data directory: A start file for the XML configuration.
  • assets/skins directory: Skins delivered with the REOPS.
 
Using the REOPS configuration XML
Follow these steps to use the REOPS configuration XML:
 
  1. Import the project into Flash Builder.
  2. Copy the OSMF SWC file from the code you should have downloaded from the OSMF site into the libs directory.
  3. Run the MyREOPS project. You should see a video play (see Figure 9).
Video playing in the initial build of MyREOPS
Figure 9. Video playing in the initial build of MyREOPS
  1. Open the reosmf_config.xml file in assets/data directory. This file is a good, basic configuration that sets up all the basic elements for a simple player.
    Note: Additional nodes and attributes can be applied to add more functionality. More information will eventually be posted on the Google Code wiki page.
     
    • The <player> node handles the player sizing and scale mode.
    • The <mediaElement> and its child <mediaElement> node handle the initial media that is displayed by the player.
    • The <skin> node configures the elements of the skin:
      • What skin SWF file to use
      • Positioning of skin elements such as the control bar and loading icon
 
Changing the size of the player
Follow these steps to change the size of the player:
 
  1. In the reosmf_config.xml file, change the width attribute value to be 768 and the height to be 600:
<player width="768" height="600" scaleMode="stretch" isLive="false" autoPlay="true" updateInterval="250" hasCaptions="false">
  1. Save the file.
  2. Run the application. The player and video should now display at the larger size (see Figure 10).
Figure 10. The video, adjusted to a larger size
Figure 10. The video, adjusted to a larger size
 
Changing the scale mode
Follow these steps to change the scale mode:
 
  1. Return to the reosmf_config.xml file.
  2. Change the scaleMode attribute value in the <player> node from stretch to letterbox.
    Note: Valid values for scaleMode are none, stretch, letterbox and zoom. For details on how each is handled, see the org.osmf.display.ScaleMode class.
     
<player width="768" height="600" scaleMode="letterbox" isLive="false" autoPlay="true" updateInterval="250" hasCaptions="false">
  1. Save the file.
  2. Run the application. The video should now be presented in a much nicer letterbox format (see Figure 11).
The video, played in letterbox format
Figure 11. The video, played in letterbox format
 
Changing the default MediaElement
Follow these steps to change the default MediaElement:
 
  1. Return to the reosmf_config.xml file.
  2. To change the media from RTMP streaming to remote progressive video, locate the <mediaElement> node. Update the <media> node's url property to the URL shown:
<mediaElement> <mediaElement> <media url="http://mediapm.edgesuite.net/strobe/content/test/AFaerysTale_sylviaApostol_640_500_short.flv" /> </mediaElement> </mediaElement>
  1. Save the file.
  2. Run the application. The new video should play (see Figure 12).
The player, pointed to a diferent video
Figure 12. The player, pointed to a diferent video
 
Setting the player skin
Follow these steps to change the player skin:
 
  1. Return to the reosmf_config.xml file.
  2. Update the path attribute of the <skin> node from:
    <skin path="assets/skins/RE_Skin.swf">
     
    to:
     
    <skin path="assets/skins/Lunar.swf">
    Note: You can try the Core.swf and Formula.swf skin files as well.
     
  3. Save the file.
  4. Run the application. You should see the different skin for the control bar (see Figure 13).
The player with a new skin swapped in via XML
Figure 13. The player with a new skin swapped in via XML
 
Positioning and auto-hiding the control bar
Follow these steps to position and auto-hide the control bar:
 
  1. Return to the reosmf_config.xml file.
  2. Locate the <skinElement> node with the id of controlBar.
  3. Update the vAdjust attribute value to be –180:
<skinElement id="controlBar" elementClass="com.realeyes.osmfplayer.controls.ControlBar" initMethod="initControlBarInstance" scaleMode="none" hAdjust="0" vAdjust="-180" hAlign="center" vAlign="bottom" autoPosition="true" draggable="true" autoHide="false" />
  1. Update the attribute value of autoHide to be true:
<skinElement id="controlBar" elementClass="com.realeyes.osmfplayer.controls.ControlBar" initMethod="initControlBarInstance" scaleMode="none" hAdjust="0" vAdjust="-180" hAlign="center" vAlign="bottom" autoPosition="true" draggable="true" autoHide="true" />
  1. Save the file.
  2. Run the application. The control bar should now be positioned over the video at the bottom (see Figure 14).
The video with control bar positioned over the bottom
Figure 14. The video with control bar positioned over the bottom
Also, if you move your mouse away from the player the control bar should auto-hide after a short period of time. The control bar should also be visible if you roll over the player again.
 

 
Deploying the REOPS player

Deploying the REOPS player is a simple process of gathering the necessary files and transferring them to your web server. Minimally you will need the following files for a REOPS deployment:
 
  • HTML page to display the player
  • Player SWF file
  • XML configuration file
  • Skin SWF file
If you use the files from the MyREOPS walkthrough project, you can deploy the REOPS player by uploading the following files from the bin-debug directory to a web server:
 
  • assets/data directory, which includes the configuration file
  • assets/skin/ directory, which includes the skin SWF files (you can remove the unused skin SWF files)
  • MyREOPS.html
  • MyREOPS.swf
  • swfobject.js

 
Where to go from here

The RealEyes OSMF Player Sample leverages some built-in tools provided by the OSMF to make developing media players a less painful and more consistent process. You should have a good idea about how the REOPS uses the OSMF to create a very configurable and flexible media player. Using the external XML configuration file, you should also be able to set up a single player SWF file for multiple uses and deployments quickly and easily.
 
In this article, we also covered some of the core concepts and components that are needed to build a media player using the OSMF:
 
  • The MediaPlayerSprite
  • MediaElements
  • Traits
  • The MediaContainer
  • The MediaFacatory
  • The NetConnectionFactory
This information should help you to build your own media players using the OSMF, even if you don't use the REOPS project as a starting point.
 
In Part 3 we will explain in detail the control bar and skinning system built into the REOPS project.
 
Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License+Adobe Commercial Rights
 
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.