Order Now AdSolution Sign Up | Login » Bits on the Run Sign Up | Login »

Open Video Ads

Integrating OVA for AS3

This tutorial walks through at a high level, the steps required to integrate the OVA for AS3 framework into a custom player.

1. Recommended Reading

The following reading is recommended to accompany this tutorial

2. The Overall Model

The following diagram illustrates an end-to-end solution using OVA.

A web-page contains a video player that embeds the OVA framework. Typically the framework is embedded via an ad streaming plugin that has been built for that player using the player's API. Examples of this are the OVA for Flowplayer and OVA for JW 5x plugins.

The OVA framework has attached to it a JSON configuration that identifies to the framework the type of video advertising to be delivered and the ad server source.

For a detailed guide on the configuration options available, consult the OVA Configuration Guide.

The framework uses the JSON configuration data along with a specification of the show streams to play to construct an ad schedule. In doing so, one or more ad server requests are fired off to an identified VAST compliant ad server to obtain the details on the ad creatives to be served by the framework. These details are returned in the form of a VAST template.

The framework parses the template, extracting and storing the details provided on each ad element.

As the show streams play, the OVA framework triggers the display of the relevant video ads based on the information provided in the VAST response, firing off the required impression and tracking events.

3. Ad and Show Scheduling

Central to the design of the OVA for AS3 framework is the notion of a Stream Sequence.

A Stream Sequence is an ad adorned playlist that results from merging a Show Playlist with an Ad Schedule. In essence, it defines the sequence of streams to be played back by the Video Player. 

The following diagram illustrates the notion of a Stream Schedule.

The Ad Schedule is specified in the OVA Configuration. The following config snippet illustrates a typical Ad Schedule definition:

....
   "ads": {
      "servers": [
         {
            "type": "OpenX",
            "apiAddress": "http://openx.openvideoads.org/openx/www/delivery/fc.php",
         }
      ],
      "schedule": [
         {
            "zone": "5",
            "position": "pre-roll"
         },
         {
            "zone": "33",
            "position": "bottom",
            "width": 450,
            "height": 50,
            "startTime": "00:00:05",
            "duration": "15"
         }
      ],
   },
....

The Show Playlist can either be defined using the standard player playlist definition mechanism or the OVA configuration structure. The following config snippet illustrates a show playlist defined via OVA:

....
   "shows": {
      "streams": [
         {
            "file":"http://streaming.openvideoads.org/shows/the-black-hole.mp4",
            "duration":"00:00:30"
         }
      ]
   },
....

In the case of the OVA for JW Player implementations, show playlists are loaded via the "file=" flashvar:

flashvars="plugins=ova&file=http://streaming.openvideoads.org/shows/the-black-hole.mp4"

In the OVA for Flowplayer case, the Flowplayer JSON based playlist configuration approach is used:

flowplayer("a.example", "flowplayer-3.2.2.swf", {
    playlist: [
       {
           url: "http://streaming.openvideoads.org/shows/the-black-hole.mp4",
           duration: 20
       },
    ],
    
    plugins: {
        ova: {
            url: "ova.swf",
            ....
        }
    }
});

OVA relies on several key assumptions:

  1. The player is responsible for playback of both show and ad streams via some type of playlist or clip API
  2. The player will provide timing information to OVA so that it knows how far it is through ad and show streams at any given time
  3. The player will provide an interface to enable/disable the player controls. OVA will provide notifications as to when the control bar state should be changed based on whether or not an ad is being played back
  4. The player will provide a handle to it's display container (and sizing information) to allow OVA to layout messages and non-linear advertising on it

4. The Overall Flow of Control

Before we walk through the high levels steps that need to be taken to integrate the framework, a great way to understand how to integrate the OVA framework into your custom player is to look at the code of a working example - for instance, the OVA for Flowplayer or OVA for JW Player 5 plugins.

Saying that, all player implementations that utilise the OVA framework will broadly work the same way.

The following diagram illustrates the OVA Flow of Control - the sequence of steps that need to be implemented to deliver an OVA enabled custom player.

The first step that is taken by a player is to load up the OVA configuration data. OVA configuration data is specified in JSON form and must be loaded into the OVA framework in either raw AS3 Object or OVA org.openvideoads.vast.config.Config format.

Once the configuration data is loaded, the next step is to initialise the framework. When initialising the framework:

  1. General operational parameters are set
  2. Listeners for OVA events are registered
  3. Handlers for Player events are registered
  4. Display parameters are set
  5. The OVA configuration data is fed into the framework

With the framework initialised, the programme schedule can be created by OVA. A Programme Schedule is an ad scheduled set of show clips that must be played back by the custom player. To create the programme schedule, the OVA framework makes the required ad server calls to get the VAST (ad) data before assessing and splicing the Ad Schedule specified in the OVA config into the playlist defined for the player to produce a unified sequence of ad and show clips (termed the StreamSequence).

Once the Stream Sequence is been created, an OVA custom player implementation is then responsible for coordinating the playback of that set of streams via the player mechanisms. In the case of both Flowplayer and JW Player, Clip based APIs are provided to allow an OVA implementation to facilitate the playback by loading each clip into the player "on demand" as the sequence progressively plays. 

In the course of managing the playback, the OVA custom implementation needs to:

  1. Track the time of stream playback (so that ad playback can be tracked)
  2. Respond to player events (such as fullscreen, start/stop/pause/resume/mute etc.)
  3. Optionally respond to OVA ad events (such as start, stop etc.) 

5. The Key Integration Points

Breaking the flow of control down a little further, in broad terms there are nine key integration points that must be covered when embedding the framework into your custom player:

  1. Loading the Show and Ad Configuration Data
  2. Initialising the Framework
  3. Managing the Loading and Playback of Clips
  4. Managing Time as Clips Playback
  5. Managing Player Events as Ads Playback
  6. Managing Player Sizing
  7. Managing Ad Events
  8. Handling Overlay Display
  9. Handling Companion Ad Display

A range of interfaces and APIs have been provided within the OVA for AS3 framework to help you navigate through these control points.

5.1 Loading The Show and Ad Configuration Data

OVA ad and show configuration data is specified in JSON form.

That data must be ingested before the framework is initialised.

The JSON data can be passed to the OVA framework in either one of two forms - as a basic AS3 Object or a fully initiated OVA org.openvideoads.vast.config.Config object.

For example, the following code snippet illustrates how the OVA for JW Player 5 plugin reads in the OVA configuration data:

...

public function initializePlugin():void {	
   doLog("Initialising plugin...", Debuggable.DEBUG_ALL);
   var rawConfig:Object;
   if(_config.json != undefined) {			
      // Load up the config and configure the debugger
      doLog("OVA config loaded as " + _config.json, Debuggable.DEBUG_CONFIG);
      rawConfig = JParser.decode(_config.json);
   }
   else doLog("No OVA configuration provided");
   _vastController = new VASTController();
   _vastController.endStreamSafetyMargin = 300;
   loadExistingPlaylist(rawConfig);			
   _vastController.initialise(rawConfig, false, this);
}

....

The OVA for JW Player plugin relies on the use of a third party JSON parser (JSwoon) to parse the raw JSON data string into an AS3 Object. Once that is done it can be passed into the VASTController via the initialise() method.

The OVA for Flowplayer plugin takes a different approach as illustrated by the following code snippet:

...

protected function initialiseVASTFramework():void {			
   // load up the Open Ad Stream JSON config
   var config:Config = 
           (new PropertyBinder(
               new Config(null, this), null).copyProperties(_model.config) as Config
           );

   // Initialise the VAST Controller
   _vastController = new VASTController();
   _vastController.startStreamSafetyMargin = 500;
   _vastController.endStreamSafetyMargin = 300; 
   _vastController.initialise(config, false, this);
}
...

The OVA for Flowplayer plugin uses the Flowplayer PropertyBinder class to read in the OVA JSON configuration from the Flowplayer plugin configuration block.

5.1.1 Maintaining Externally Declared Playlists

At it's core, the OVA for AS3 framework is an ad scheduler. It is not possible for OVA to schedule a series of ads to play unless a set of one or more show streams are first declared.

Show streams can be declared using either the standard player configuration mechanisms (e.g. playlist configuration for Flowplayer, file= flashvar for JW Player etc.) or internally via the "shows" configuration block within the OVA configuration data.

The following configuration snippet illustrates a typical Flowplayer style playlist declaration.

flowplayer("a.example", "flowplayer-3.2.2.swf", {
    playlist: [
       {
           url: "images/logo.png",
           scaling: "orig"
       },
       {
           url: "mp4:the-black-hole.mp4",
           provider: "rtmp",
           duration: 15
       },
       {
           url: "http://streaming.openvideoads.org/shows/the-black-hole.mp4",
           duration: 20
       },
    ],
    
    plugins: {
        rtmp: {
            url: "flowplayer.rtmp-3.1.3.swf",
            netConnectionUrl: "rtmp://ne7c0nwbit.rtmphost.com/videoplayer"
        },

        ova: {
            url: "ova.swf",
            
            "ads": {
              "servers": [
                   {
                      "type": "OpenX",
                      "apiAddress": "http://openx.openvideoads.org/openx/www/delivery/fc.php",
                   }
              ],
              "schedule": [
                  {
                     "zone": "5",
                     "position": "pre-roll",
                     "applyToParts": [1, 2]
                  }
              ]
            }
        }
    }
});

When the OVA for AS3 framework is initialised, any pre-declared playlist settings must be converted from the native player format to an internal OVA "streams" configuration. 

For example, the following abbreviated code snippet illustrates how this is achieved by the OVA for Flowplayer plugin.

protected function initialiseVASTFramework():void {			
   // load up the Open Ad Stream JSON config
   var config:Config = 
        (new PropertyBinder(
           new Config(null, this), null).copyProperties(_model.config) as Config
        );

   // Preserve the playlist if one has been specified and set that as the 
   // "shows" config before initialising the VASTController
			
   if(_player.playlist.clips.length > 0 && _player.playlist.clips[0].url != null) {
      if(config.hasStreams()) {
         config.prependStreams(convertFlowplayerPlaylistToShowStreamConfig());
      }
      else config.streams = convertFlowplayerPlaylistToShowStreamConfig();
   }

   ....
}				

protected function convertFlowplayerPlaylistToShowStreamConfig():Array {
   var showStreams:Array = new Array();
   for(var index:int=0; index < _player.playlist.clips.length; index++) {
       showStreams.push(
          new StreamConfig(
                _player.playlist.clips[index].url,
                ....
          ); 
   }
   return showStreams;
}

Playlists are maintained by converting each clip in a playlist to a StreamConfig object. The OVA config object has a property called "streams" that is an array of StreamConfig objects. When the OVA framework initialises and starts the ad scheduling process, it takes the list of show streams from this "streams" property.

5.2 Initialising the Framework

The OVA framework managed by a master controller class org.openvideoads.vast.VASTController

To initialise the framework, that class must be initiated and several methods called to configure it for operation.

Initialisation involves the following steps and decisions:

5.2.1 Being Notified When the Configuration Data Is Loaded

In both the Flowplayer and JW Player OVA plugins you will notice that two config related interfaces are implemented (as defined by org.openvideoads.vast.config.ConfigLoadListener).

Both of these interfaces help support the loading of chained configuration within the OVA configuration block (e.g. externally referenced RSS, SMIL playlists etc. that may specified in the OVA "shows" configuration block and as such load asynchronously via HTTP calls triggered as the config is loaded)

isOVAConfigLoading():Boolean
onOVAConfigLoaded():void

isOVAConfigLoading() can be called to identify if the configuration data is in the process of being loaded. Typically an implementation of this method will make a call to the VASTController.isOVAConfigLoading() method to determine if the controller is in the process of loading the configuration data.

onOVAConfigLoaded() is called by the VASTController when the configuration data is fully loaded.

A detailed tutorial entitled The OVA Approach to Configuration is provided to help you understand how best to manage, parse and store the OVA configuration data prior to initialising the framework.

5.2.2 Specifying the Framework Operating Parameters

When the framework operates, many of the events are tied to timing events generated by the player as streams start and stop. In some players, it is best for OVA to offset the initial set of timing events by a small margin to ensure that the player can deal with all of these tasks occurring in rapid succession.

For example, in the case of the OVA for Flowplayer implementation, the start of stream events are offset 500 milliseconds after the stream has started, while the end of stream events are required 300 milliseconds before the end of the stream. To support this type of offsetting, the following code is used when the OVA framework is initialised.

_vastController.startStreamSafetyMargin = 500;   // cuepoints at 0 for FLVs don't fire	
_vastController.endStreamSafetyMargin = 300;     // SWF interactive linears don't fire correctly at end	

5.2.3 Specifying the Player Stage Dimensions

OVA supports the notion of StageDimensions (org.openvideoads.regions.config.StageDimensions) to specify the padding values that are to be applied at the bottom of the player screen to account for the presence or absence of the player control bar.

When the control bar is visible, overlays should be shown just above the control bar on the player screen, however when the control bar is not visible, they should be shown a few pixels above the bottom of the screen.

It is possible to specify the padding values to be used in the OVA configuration block. If they are not set however, the appropriate values for the custom player should be set on the framework during initialisation. For example, in the case of the OVA for Flowplayer plugin, the following code is used:

if(!_vastController.hasStageDimensions()) {
   _vastController.stageDimensions = new StageDimensions(25, 5);
}

5.3 Managing the Loading and Playback of Clips

The bulk of an OVA custom player implementation revolves around the management of the loading and playback of the OVA constructed, ad injected programme schedule.

Once the VASTController has been initialised and the OVA configuration data fully loaded, the programme schedule can be constructed by OVA.

5.3.1 Making the Ad Server Calls

Before the schedule can be constructed however, OVA must identify and make the required ad server calls to obtain the VAST response(s). 

The following code snippet illustrates how that is done in the OVA for Flowplayer plugin:

_vastController.load();	

....

protected function onTemplateLoaded(event:TemplateEvent):void {
    doLogAndTrace("NOTIFICATION: VAST data loaded - ", event.template, Debuggable.DEBUG_FATAL);
    _player.playlist.replaceClips2(_clipList);
    _model.dispatchOnLoad();
}

The OVA for Flowplayer plugin implements the org.openvideoads.vast.model.TemplateLoadListener interface that declares:

protected function onTemplateLoaded(event:TemplateEvent):void;
protected function onTemplateLoadError(event:TemplateEvent):void;

Calls to the ad server are triggered via the VASTController.load() API. When called, the VASTController constructs a request for the specified Ad Server, fires it off to the ad server, waits for a response (which should be the VAST data), processes the response, constructs an object model representing the VAST ad data before calling back the OVA plugin call via the method listening for the TemplateEvent.LOADED event. A VideoAdServingTemplate can be obtained from the TemplateEvent via the attribute.

In between constructing the original ad server request and the dispatch of the TemplateEvent.LOADED event, a lot of processing occurs within the OVA framework. The four key activities undertaken by the framework during this period are:

  1. The formation of the ad server request The parsing of the VAST response to create a VideoAdServingTemplate
  2. The mapping of the Ads in the VideoAdServingTemplate to the AdSchedule
  3. The construction of a StreamSequence based on the shows configuration and the streams identified in the AdSchedule
  4. The dispatching and processing of Ad and Stream scheduling events back to the class implementing the org.openvideoads.vast.model.TemplateLoadListener interface

5.3.2 Enabling/Disabling the Control Bar

When a linear ad stream plays, the control bar should be disabled to ensure that the viewer cannot fast forward or skip the ad stream.

The custom player implementation must handle this functionality by registering a listener for the SeekerBarEvent.TOGGLE event.

_vastController.addEventListener(SeekerBarEvent.TOGGLE, onToggleSeekerBar);

The following code snippet illustrates how the OVA for Flowplayer implementation handles this event:

public function onToggleSeekerBar(event:SeekerBarEvent):void {
   if(_vastController.disableControls) {
      if(!event.turnOff()) {
	  turnOnControlBar();
      }	 
      else turnOffControlBar();
   }
   else doLog("NOTIFICATION: Ignoring request to change control bar state");
}

5.4 Managing Time As Clips Playback

Time management is a very important topic for the OVA framework. The IAB defines a series of impression and tracking events that must be fired as a video ad is played.

To deliver this functionality, the VASTController constructs a series of time tracking tables when it constructs the Ad and Stream schedules. Each stream in a Stream Sequence has a TrackingTable attached. The tracking table identifies the tracking points that must be fired as the stream plays. These tracking points recorded for each stream include:

  1. For Show streams
    1. Stream start
    2. Stream end
  2. For Ad Streams
    1. Ad start and related events such as show ad notice
    2. Companion start and end
    3. Non-Linear start and end
    4. Linear Ad first quartile
    5. Linear Ad midpoint
    6. Linear Ad third quartile
    7. Linear Ad completion and related events

A point in time is recorded against each tracking point. When that point is hit as the stream plays back, the TrackingEvent is fired. The only way OVA knows when to fire a tracking point is via TimeEvents that the Player must fire into the OVA framework via the VASTController.processTimeEvent() method.

For example, the OVA for JW Player plugins use the standard time tracking mechanism provided by the JW Player API which sees a time based event fired to a JW Plugin every 1/10th of a second. The following code snippet illustrates how a listener for the JW time event is setup, and how that time is forwarded onto the VASTController to be processed by the framework:

public function onOVAConfigLoaded():void {	
   ...
   _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_TIME, timeHandler);
}

private function timeHandler(evt:MediaEvent):void {
   if(evt.position > 0) {
      ...
      if(!_vastController.isActiveOverlayVideoPlaying()) {
         _lastTimeTick = evt.position;
         _vastController.processTimeEvent(
                 getActiveStreamIndex(), 
                 new TimeEvent(evt.position * 1000, evt.duration)
         );		
      }
      else { 
         _vastController.processOverlayLinearVideoAdTimeEvent(
                 _activeOverlayAdSlotKey, 
                 new TimeEvent(evt.position * 1000, evt.duration)
         );
      }
   }				
}

The OVA for Flowplayer plugin alternatively uses the standard Flowplayer Cuepoint Clip API that allows specific points in time on a clip to be registered with Flowplayer. When Flowplayer hits that point in time during the playback of a clip, a time event is fired into the Flowplayer plugin. A key operation then in the OVA for Flowplayer setup is the establishment of these Cuepoints. The OVA for Flowplayer plugin relies on the non-linear and linear scheduling events generated by the VASTController to trigger the registering of the appropriate Cuepoints based on the timings registered against Ad Slot tracking tables.

The following code snippet illustrates how the OVA for Flowplayer plugin uses this cuepointing approach to notify the VASTController of a new point in time.

public function onOVAConfigLoaded():void {
   ...
}

protected function setupTrackingCuepoints(clip:Clip, trackingTable:TrackingTable, scheduleIndex:int):void {
   // Setup the flowplayer cuepoints based on the tracking points defined for this stream 
   // (including companions attached to linear ads)
   clip.removeCuepoints();
   for(var i:int=0; i < trackingTable.length; i++) {
       var trackingPoint:TrackingPoint = trackingTable.pointAt(i);
       if(trackingPoint.isLinear()) {
          clip.addCuepoint(
             new Cuepoint(trackingPoint.milliseconds, 
                          trackingPoint.label + ":" + scheduleIndex
             )
          );
          doLog("Flowplayer Linear CUEPOINT set at " + trackingPoint.millisecond);						
       }
   }			
}

...
    clip.onCuepoint(processCuepoint);
...

protected function processCuepoint(clipevent:ClipEvent):void {
   var cuepoint:Cuepoint = clipevent.info as Cuepoint;
   var streamIndex:int = parseInt(cuepoint.callbackId.substr(3));
   var eventCode:String = cuepoint.callbackId.substr(0,2);
   doLog("Cuepoint triggered " + clipevent.toString() + " - id: " + cuepoint.callbackId);
   _vastController.processTimeEvent(
       streamIndex, 
       new TimeEvent(clipevent.info.time, 0, eventCode)
   );            	            
}

5.5 Managing the Player Events

A number of player related actions need to be tracked by the OVA for AS3 framework to ensure that the required IAB tracking events are triggered as ads are shown.

These events include:

To support the capture of player related events, a number of event methods are provided on the VASTController. When an important event is picked up by a player implementation, the appropriate VASTController method should be called to register that event with the framework. 

For example, the OVA for JW Player 5 implementation uses the following code to capture a pause event on a stream and pass that where appropriate through to the VASTController.

...
    _player.addEventListener(ViewEvent.JWPLAYER_VIEW_PAUSE, onPauseEvent);
...

private function onPauseEvent(evt:ViewEvent):void {
       	if(_vastController != null) {
		if(_vastController.isActiveOverlayVideoPlaying()) {
      			_vastController.onPlayerPause(_activeOverlayAdSlotKey, true);
      		}
      		else _vastController.onPlayerPause(getActiveStreamIndex());
       	}
       	_playerPaused = true;
}

5.6 Managing Player Sizing

Given that the OVA framework controls the display of ad notices and overlays, it is important that the framework always be aware of the latest player sizing. When the player sizing changes, the positioning and dimension of the pre-defined regions and active overlays needs to change.

In the case of the OVA for Flowplayer plugin, resizing is implemented via the Flowplayer Plugin resize() method as follows:

override protected function onResize():void {
    super.onResize();
    if(_vastController != null) {
         _vastController.resizeOverlays(
                new DisplayProperties(
                         this, 
                         width, 
                         height, 
                         _vastController.stageDimensions.withControlsPaddingBottom,
                         _originalWidth, 
                         _originalHeight
                )
        );
    }
}

You will notice that when the display properties are passed into the VASTController, the padding value to use is passed. In the case above, the padding value when the control bar is active at the bottom is passed indicating that the control bar is visible.

If the control bar was to disappear, overlays can be resized/positioned to take that into account by passing a new set of DisplayProperties in that include _vastController.stageDimensions.noControlsPaddingBottom

5.7 Managing Ad Events

As the OVA for AS3 framework processes ads, ad events are generated. It is possible to register listeners for a range of these events.

The following code snippet illustrates how to implement these listeners. The listeners should be added when the VASTController is initialised.

...

   _vastController.addEventListener(LinearAdDisplayEvent.STARTED, onLinearAdStarted);
   _vastController.addEventListener(LinearAdDisplayEvent.COMPLETE, onLinearAdComplete); 
   _vastController.addEventListener(LinearAdDisplayEvent.CLICK_THROUGH, onLinearAdClickThrough);           
   _vastController.addEventListener(CompanionAdDisplayEvent.DISPLAY, onDisplayCompanionAd);
   _vastController.addEventListener(CompanionAdDisplayEvent.HIDE, onHideCompanionAd);
   _vastController.addEventListener(OverlayAdDisplayEvent.DISPLAY, onDisplayOverlay);
   _vastController.addEventListener(OverlayAdDisplayEvent.HIDE, onHideOverlay);
   _vastController.addEventListener(OverlayAdDisplayEvent.DISPLAY_NON_OVERLAY, onDisplayNonOverlay);
   _vastController.addEventListener(OverlayAdDisplayEvent.HIDE_NON_OVERLAY, onHideNonOverlay); 
   _vastController.addEventListener(OverlayAdDisplayEvent.CLICKED, onOverlayClicked);
   _vastController.addEventListener(OverlayAdDisplayEvent.CLOSE_CLICKED, onOverlayCloseClicked);
   _vastController.addEventListener(AdNoticeDisplayEvent.DISPLAY, onDisplayNotice);
   _vastController.addEventListener(AdNoticeDisplayEvent.HIDE, onHideNotice);

...

public function onLinearAdStarted(linearAdDisplayEvent:LinearAdDisplayEvent):void {
   doLog("NOTIFICATION: Event received that linear ad has started", Debuggable.DEBUG_DISPLAY_EVENTS);
}	

...

5.8 Handling the Display of Overlays

One of the advantages of the OVA framework is that it can take care of the display of non-linear (overlay) advertising for the Video Player. The OVA for Flowplayer and JW Player plugins makes use of this.

5.8.1 Enabling Auto Display of Overlays

To turn on control of the non-linear advertising, the plugin makes the following call to the VASTController

_vastController.enableNonLinearAdDisplay(new DisplayProperties(this, 640, 360, 25));

This call requires a DisplayProperties object to be passed into the VASTController. The DisplayProperties instance defines the size of the player and a reference to the player's DisplayContainer so that the overlay Sprite can be added to the display container and shown.

For a detailed description of how to configure regions, please refer to the Configuration Guide.

5.8.2 Listening for Overlay Events

It is possible to register listeners for Overlay display events.

The following initialisation code illustrates how listeners for these events are registered:

_vastController.addEventListener(OverlayAdDisplayEvent.DISPLAY, onDisplayOverlay);
_vastController.addEventListener(OverlayAdDisplayEvent.HIDE, onHideOverlay);

The "display" event is fired when the framework determines that the overlay is to be shown while the "hide" is fired when the overlay is to be removed. The framework fires these events regardless of whether or not it is responsible for the display and hiding of overlays on the player.

5.8.3 Supporting Non-Linear (Overlay) 'Click to play a Video Ad'

Non-linear advertising that supports the notion of "click me to start a video ad" has to be treated slightly differently by OVA custom player implementations than standard display or "click through to a website" overlays.

The key difference is that a non-linear overlay that allows a video to be played in essence has a linear ad attached to it. From the perspective of the OVA for Flowplayer or JW Player plugins when the user clicks on an overlay to fire up the video, the player must insert the Video Ad "instream" to the current show clip.

In the case of the OVA for Flowplayer plugin, the implementation captures the overlay "click" event via the OverlayAdDisplayEvent.CLICKED event listener and processes it accordingly.

The following code snippet is from the Ad Streamer and is responsible for processing the click event on the overlay.

...
_vastController.addEventListener(OverlayAdDisplayEvent.CLICKED, onOverlayClicked);
...

public function onOverlayClicked(displayEvent:OverlayAdDisplayEvent):void {
   doLog("NOTIFICATION: Event received - overlay has been clicked!");
   if(displayEvent.ad.hasAccompanyingVideoAd()) {
        var clip:ScheduledClip = new ScheduledClip();
        var overlayAdSlot:AdSlot = _vastController.adSchedule.getSlot(displayEvent.adSlotKey);			
        clip.type = ClipType.fromMimeType(overlayAdSlot.mimeType);
        clip.start = 0;
        clip.originalDuration = overlayAdSlot.getAttachedLinearAdDurationAsInt();
        clip.duration = clip.originalDuration;
        clip.key = displayEvent.adSlotKey;
        clip.isOverlayLinear = true; 
        clip.setCustomProperty("metaData", overlayAdSlot.metaData);
        if(overlayAdSlot.isRTMP()) {
            clip.url = overlayAdSlot.streamName;
            clip.setCustomProperty("netConnectionUrl", overlayAdSlot.baseURL);
            clip.provider = _vastController.getProvider("rtmp");
        }
        else {
            clip.url = overlayAdSlot.url;
            clip.provider = _vastController.getProvider("http");
        }
        PlayerConfig.setClipConfig(clip, overlayAdSlot.playerConfig);

        // Setup the flowplayer cuepoints based on the tracking points defined for this 
        // linear ad (including companions attached to linear ads)

        clip.onCuepoint(processOverlayVideoAdCuepoint);
        var trackingTable:TrackingTable = overlayAdSlot.getTrackingTable();
	for(var i:int=0; i < trackingTable.length; i++) {
	     var trackingPoint:TrackingPoint = trackingTable.pointAt(i);
	     if(trackingPoint.isLinear() && trackingPoint.isForLinearChild) {
		clip.addCuepoint(
                   new Cuepoint(trackingPoint.milliseconds, 
                                trackingPoint.label + ":" + displayEvent.adSlotKey
                   )
                );
 	     }
	}
	_player.playInstream(clip);
    }
    else _player.pause();
}

Reviewing the code snippet there are a few interesting things to note about the way the OVA for Flowplayer implementations uses the OVA for AS3 framework:

5.9 Handling the Display of Companions

The OVA framework is capable of handling the display of companions without the need for a custom player to implement the functionality to embed the companion code into a web page.

If however you wish to implement this type of functionality, two callback events are fired when companion ads are to be shown:

public function onDisplayCompanionAd(ce:CompanionAdDisplayEvent):void;
public function onHideCompanionAd(ce:CompanionAdDisplayEvent):void;

To receive these events, register the following listeners when initialising the VASTController:

_vastController.addEventListener(CompanionAdDisplayEvent.DISPLAY, onDisplayCompanionAd);
_vastController.addEventListener(CompanionAdDisplayEvent.HIDE, onHideCompanionAd);

5.10 Ensuring a Linear Ad plays only once

Finally, OVA can support playing ads just once. This is achieved by specifying the "playOnce" config option either at an Ad Slot or general Ad level:

...
    "ads": {
        "deliveryType": "streaming",
        "playOnce": true,
        "server": {
            "type": "OpenX",
            "vastURL": "http://openx.bouncingminds.com/openx/www/delivery/fc.php"
        },
        "schedule": [
            {
                "zone": "5",
                "position": "pre-roll"
            }
        ],
    },
...

In this instance the pre-roll ad will only be played once, but only if the OVA player implementation takes account of it as part of the overall playlist management code. For instance, the OVA for Flowplayer plugin achieves this by implementing specific handlers that are triggered before each clip plays - a check is done to see if the ad has already played - if it has, it is skipped as illustrated by the code snippet below:

protected function registerPlayOnceHandlers():void {
    // Before the clip plays, check if it has already been played
    _player.playlist.onBegin(
         function(clipevent:ClipEvent):void { 
   	    if(_vastController.playOnce) {
 	        var currentClip:ScheduledClip = _player.currentClip as ScheduledClip;
		if(currentClip.marked) {
                    doLog("Skipped clip at playlist index " 
                          + _player.playlist.currentIndex 
                          + " as it's already been played", Debuggable.DEBUG_PLAYLIST);
		    _player.next();		        			
		}  
            }
         } 
    );

    // Before the clip finishes, mark is as having been played
    _player.playlist.onBeforeFinish(
         function(clipevent:ClipEvent):void { 
            if(_vastController.playOnce) {
		var currentClip:ScheduledClip = _player.currentClip as ScheduledClip;
	 	if(_vastController.streamSequence.streamAt(_player.playlist.currentIndex) is AdSlot) {
		   currentClip.marked = true;
	 	   doLog("Marking the current clip (index " 
                         + _player.playlist.currentIndex 
                         + ") - it's an ad that has been played once", 
                         Debuggable.DEBUG_PLAYLIST);
	 	   }
                }
            }
    );
}