Getting started: OSMF Plugins

In the past media players have had a problem. They all have custom implementations. When building a media player the developer encounters multiple services to load content, track analytics & quality of service information as well as handle advertising & custom user interactions among other things. The Open Source Media Framework (OSMF) provides a solution to these issues by introducing a flexible plugin system that can integrate multiple plugins to solve these problems without the media player developer needing to write a bunch of extra code.

What is an OSMF plugin?

An OSMF plugin is an easily distributable extension for an OSMF based player that can unobtrusively provide or adjust the functionality of that player. At its most basic, a plugin is a class or set of classes (static plugin) or a SWF (dyanamic plugin) file that is loaded into the media player by the MediaFactory. The plugin is built to a specific API that adheres to a contract that OSMF has created so the media player knows what plugins are interested in which MediaElements and can pass them the necessary data for the plugin to do its job.

Types of plugins

There are 3 types of plugins that you can create, and each one has a different type of purpose Standard, Proxy & Reference.

  1. Standard plugins are responsible for creating either built-in or custom MediaElements.
  2. Proxy plugins are responsible for changing MediaElements that have been created by the MediaFactory.
  3. Reference plugins are responsible for adding functionality to the MediaElements created by the MediaFactory.

*NOTE: The MediaFactory must be used for plugins to work correctly. When a MediaElement is created by the MediaFactory, the MediaFactory references a list of MediaFactoryItems defined in the PluginInfo class to be notified if a plugin can handle a specific media resource.

Building an OSMF plugin

Initially I like to develop a plugin as a static or class based plugin. This allows for easier debugging and keeps things simpler when testing and/or refactoring. And it is pretty easy to convert a static plugin to a dynamic plugin, so don’t be worried about that.

The PluginInfo class is the first class you will need to be familiar with when building plugins. This class provides the API and information for the MediaFactory to access and provide the necessary data for the plugin to function correctly.

To create your PluginInfo class, you will need to extend OSMF’s PluginInfo class. The definitions for what and how a plugin can handle a MediaElement as well as what type of plugin is being loaded are specified using a collection MediaFactoryItems. In the constructor of your PluginInfo class you will need to define a MediaFactoryItem for each type of MediaElement you plan to handle and/or create in your plugin and add this to an ArrayCollection that is passed to the super’s constructor.

[actionscript3]package com.realeyes.osmf.plugin
{
import com.realeyes.osmf.plugin.element.WatermarkElement;

import org.osmf.media.MediaElement;
import org.osmf.media.MediaFactoryItem;
import org.osmf.media.MediaResourceBase;
import org.osmf.media.PluginInfo;
import org.osmf.metadata.Metadata;
import org.osmf.net.NetLoader;

public class WatermarkPluginInfo extends PluginInfo
{
public function WatermarkPluginInfo()
{
// Add MediaFactoryItems
var items:Vector.<MediaFactoryItem> = new Vector.<MediaFactoryItem>();

var loader:NetLoader = new NetLoader();
items.push( new MediaFactoryItem(
"com.realeyes.osmf.plugins.WatermarkPlugin",
canHandleResource,
createWatermarkElement
) );

super( items );
}

public function canHandleResource( resource:MediaResourceBase ):Boolean
{
return true;
}

public function createWatermarkElement():WatermarkElement
{
// Create the watermark element
var newWatermarkElement:WatermarkElement = new WatermarkElement()
return newWatermarkElement;
}
}
}[/actionscript3]

The sample class above shows the basics to defining a Standard plugin that creates a WatermarkProxyElement for any type of resource. The constructor defines a single MediaFactoryItem that creates a WaterMarkElement via the createWatermarkElementI() method. This plugin will be used for any type of MediaElement that the MediaFactory creates because the canHandleResource() method returns true. If we wanted this plugin to only handle RTMP streams we could adjust the canHandleResource() method to look something like the following:

[actionscript3]
public function canHandleResource( resource:MediaResourceBase ):Boolean
{
var canHandle:Boolean;
var urlResource:URLResource = resource as URLResource;
if( urlResource.url.indexOf( "rtmp" ) )
{
canHandle = true;
}

return canHandle;
}
[/actionscript3]

The WaterMarkElement is then returned to the MediaFactory and passed on to be handled by the media player.

Standard Plugin details

Standard plugins are used to create MediaElements. This means that they should concentrate on the resource being passed in and create the appropriate MediaElement based on that resource.

A proxy plugin

If we wanted to create a Proxy plugin we can keep the same PluginInfo class, but we’ll need to add in a 4th parameter to the MediaFactoryItem to let the MediaFactory know that it will be working with a proxy plugin and to call the proxiedElement setter on the WatermarkElement created via the createWatermarkElement() method. This would look like:

[actionscript3 highlight=”11″]
public function WatermarkPluginInfo()
{
// Add MediaFactoryItems
var items:Vector.<MediaFactoryItem> = new Vector.<MediaFactoryItem>();

var loader:NetLoader = new NetLoader();
items.push( new MediaFactoryItem(
"com.realeyes.osmf.plugins.WatermarkPlugin",
canHandleResource,
createWatermarkElement,
MediaFactoryItemType.PROXY
) );

super( items );
}
[/actionscript3]

Proxy Plugin details

Proxy plugins allow a developer to non-invasively alter the MediaElement’s behavior. For example, you could use a proxy plugin to disable the seek or pause functionality in a media stream. You can also use proxy plugins to alter the type of MediaElement after the plugin is loaded. In this case you could create a SerialElement, add a pre-roll VideoElement to the serial element and then the original MediaElement for simplified pre-roll advertising.

A reference plugin

A reference plugin is created by adding a mediaElementCreationNotificationFunction() method to the plugin and then passing that method to the super() call with the MediaFactoryItems collection. These additions would change the PluginInfo class to look like:

[actionscript3]
public function WatermarkPluginInfo()
{
// Add MediaFactoryItems
var items:Vector.<MediaFactoryItem> = new Vector.<MediaFactoryItem>();

var loader:NetLoader = new NetLoader();
items.push( new MediaFactoryItem(
"com.realeyes.osmf.plugins.WatermarkPlugin",
canHandleResource,
createWatermarkElement
) );

super( items, mediaElementCreated );
}

protected function mediaElementCreated( element:MediaElement ):void
{
trace( "MediaElement created!" );
}
[/actionscript3]

Reference Plugin Details

Reference plugins rely on having a reference to the MediaElement’s created by the MediaFactory. Unlike the proxy plugin, which receives the created MediaElements after it has been loaded a reference plugin receives a notification for each MediaElement that has been created, even those before the plugin was loaded. Reference plugins are good containers for tracking as well as interaction control.

The Power of OSMF Plugins

The Open Source Media Framework & the Plugin system provides a flexible and powerful solution to some common problems that media player in the past have had – the need to communicate with many, disparate services and content providers and the custom code implementations around these communications.  OSMF makes it easy to integrate plugins that have been built by these service and content providers as well as create plugins that extend the functionality of players built using OSMF.

Below is the presentation that I gave with David Hassoun to the Rocky Mountain Adobe Users Group on August 8th, 2010 about OSMF & Plugins.

Resources

Sample Code Download

[dm]10[/dm]

Comments
  1. Fredrik
  2. jccrosby
  3. Fredrik
    • jccrosby
  4. Fredrik
  5. Fredrik
  6. Fredrik
  7. Fredrik
    • jccrosby
  8. Fredrik
  9. Fredrik
    • jccrosby
  10. WebAppEngineer
  11. Christoper
  12. Johnnie

Leave a Reply

Your email address will not be published. Required fields are marked *