Channels ▼
RSS

JVM Languages

The OCAP Digital Video Recorder Specification

Source Code Accompanies This Article. Download It Now.


December, 2005: The OCAP Digital Video Recorder Specification

Linden is a consultant engineer at Pace Micro Technologies Americas where he works on DVR software architecture. He is the author of Core Java Media Framework (Prentice-Hall, 1999). He can be contacted at lindend@mindspring.com.


The instant a DVR is released, hordes of hackers descend on it to figure out how to add additional hard-drive capacity and tweak the software. Hacking DVRs is popular because manufacturers don't use open APIs and discourage software tweaking of their DVRs. Fortunately, CableLabs (the R&D consortium for the cable television industry) has published the OCAP Digital Video Recorder (DVR) specification that defines an open API that should minimize the need to hack future DVRs based on this technology. In this article, I examine the OCAP DVR spec and show how you use it to create DVR applications.

Monopoly Versus Competition

The software in virtually all cable DVR platforms is proprietary and highly secretive (the exception being TiVo's HME; see "Building on TiVo", DDJ, March 2005). To create applications for these proprietary platforms, you usually must sign a Non-Disclosure Agreement (NDA) and pay DVR vendors tens of thousands of dollars before obtaining an SDK. Hackers typically don't have thousands of dollars to spend and often won't sign NDAs as a matter of principle. Consequently, they resort to other means of tweaking the software.

At the same time, the cable industry is trying to transition from legacy cable boxes with proprietary APIs to a Java-based API set called the "OpenCable Application Platform" (OCAP); see my article "The OpenCable Application Platform" (DDJ, June 2004). While the initial OCAP specification has a rich API set that can control High Definition (HD) and advanced captioning features found in modern set-top boxes, it is sorely lacking Video Recording (VR) functionality. Fortunately, this was not an intentional omission. The OCAP spec was released before DVRs became mainstream devices and CableLabs did not try to cram a preliminary DVR specification into the standard before it was solidified.

In the years since the original OCAP spec was published, HD DVRs have exploded onto the market and became key revenue generators for many cable vendors. Consequently, CableLabs realized that the addition of a Java-based DVR API was an essential if OCAP wanted widespread acceptance. Consequently, it published the OCAP Digital Video Recorder (DVR) specification (http://opencable.com/downloads/specs/OC-SP-OCAP-DVR-I02-050524.pdf).

Bare Minimum

CableLabs has three goals for OpenCable:

  • Define the feature set of next-generation hardware.
  • Foster competition based on open standards.
  • Enable boxes to be sold at retail locations.

To further these goals, CableLabs created OCAP—a middleware API that is operating system, hardware, and network neutral. By eliminating all proprietary operating systems and conditional access technologies, OCAP ensures competition by defining an open standard and allowing vendors to innovate based on their particular expertise.

CableLabs has adopted a similar approach with the OCAP DVR extension. Rather than taking an authoritarian approach and forcing all vendors to create clone DVR products, the DVR spec defines the minimum set of standards that any OCAP DVR platform must support. Vendors can differentiate themselves via enhanced functionality, price, or time to market. CableLabs only insists that each OCAP DVR implement the API it defines and provide the hardware capabilities it requires. This ensures that OCAP-certified DVR applications run on any OCAP-compliant DVR platform.

Each OCAP DVR box has at least one tuner, one time-shift buffer per tuner, local storage for digital video playback/recording, and local storage for a general-purpose filesystem. As I described in "Inside Digital Video Recorders" (DDJ, July 2005), a tuner is used to obtain live content from the satellite or cable network and the time-shift buffer lets you perform trick operations (fast forward or pause, for instance) on the live content.

CableLabs has also wisely differentiated file operations on a general-purpose filesystem (NTFS, ext2, ext3, and the like) from recording and playing back content to a storage device. On some DVRs, a general-purpose filesystem (GPFS) is used to store both content and data files. By contrast, other DVRs use a specialized filesystem for recording and playing back content. Typically, these filesystems are highly optimized for large block reads and writes, and shouldn't be cluttered with small data files (some may not even let you create small files or use traditional file I/O APIs). Therefore, the OCAP DVR API offers APIs to detect if the medium is capable of general-purpose file I/O and content storage or retrieval (or both).

In addition to these basic hardware features, every OCAP DVR is capable of recording live content, playing or watching TV while recording, obtaining a listing of all available recordings, performing resource management, attaching permissions to content, and enforcing rights management and copy protection.

Inverse Evolution

The first wave of OCAP specifications tweaked existing European-based Multimedia Home Platform (MHP) Globally Executable MHP (GEM) specifications for North American cable products (http://www.mhp.org/mhp_technology/ other_mhp_documents/tam0927-pvr-pdr-dvr-for-www-mhp-org.pps). By contrast, the initial iteration of the OCAP DVR spec was specifically designed for North American products and was not based on an existing European standard.

At the same time, DVB was adding its own flavor of DVR functionality to GEM. Because both efforts were based on MHP and contained many common elements, CableLabs and MHP decided to merge the core functionality in both DVR working groups to create the shared standard "Digital Recording Extension to Globally Executable MHP" (MHP document number A088; see http://www.mhp.org/mhp_technology/other_mhp_documents/mhp_a088.zip).

All A088 classes and interfaces are found in the org.ocap.shared namespace. However, if you try to create a Java-based DVR application using only A088, you'll be bitterly disappointed when the compiler spews out an avalanche of errors when you compile it. This is because A088 provides common DVR interfaces and abstract classes that could be used on satellite, cable, or terrestrial products. It is missing key network and resource management classes needed to compile and link. CableLabs and MHP intentionally avoided these topics because this functionality varies dramatically between European (DVB) and North American cable environments. Consequently, A088 must be supplemented with concrete classes to create a viable DVR solution.

In OCAP, these concrete classes are located in the org.ocap.dvr namespace and are defined in the OCAP DVR spec. OCAP offers classes to handle features such as filesystems, resource, and network management. MHP's implementation is found in the A087 spec (http://www.mhp.org/mhp_technology/other_mhp_documents/mhp_a087.zip). It permits DVR applications to access European-oriented DVB Service Information (SI) and TVAnytime Java classes (TVAnytime defines features such as metadata to describe content).

Storage Search

Given that DVRs focus on playing back content, the first thing a DVR application typically does is detect the storage devices connected to the platform. This information resides in the StorageManager, a system object that monitors the availability of all storage-related devices. To obtain a listing of mounted filesystems, you call StorageManager.getStorageProxies(). This returns an array of StorageProxy objects.

StorageProxies implement a variety of interfaces, the most interesting of which are DetachableStorageOption, LogicalStorageVolume, and MediaStorageVolume. The DetachableStorageOption interface is implemented by a StorageProxy that can be hot-plugged (or dynamically added or removed). These type of StorageProxy objects will be found on DVR platforms that have IEEE 1394, SATA, or USB 2.0 port(s). It is important to test if the StorageProxy implements DetachableStorageOption before attempting file I/O on it because the filesystem may need to be mounted before it is used. The filesystem may be mounted by calling DetachableStorageOption.makeReady() and unmounted via DetachableStorageOption.makeDetachable().

When a storage device is hot-plugged, the StorageManager generate events to all interested parties that have attached a listener via the addStorageManagerListener() method. These events are divided into three categories:

  • STORAGE_PROXY_ADDED. A storage device was added to the DVR.
  • STORAGE_PROXY_CHANGED. A storage device changed state (for example, the filesystem may be mounted or unmounted).
  • STORAGE_PROXY_REMOVED. A storage device was removed from the DVR.

The second interface surfaced by StorageProxies is LogicalStorageVolume. Again, some DVR storage devices may not permit you to perform general-purpose file I/O on them. If the StorageProxy implements LogicalStorageVolume, then you can get path information via the LogicalStorageVolume.getPath() and set file attributes with LogicalStorageVolume.setFileAccessPermissions().

The third critical interface exposed by a StorageProxy is MediaStorageVolume. Storage devices that host digital video and multimedia content implement the MediaStorageVolume interface. It offers methods to report total space available to record content and the maximum bitrate of content it can record or playback. This is vital information because you don't want to record a 20-MBps High Definition stream onto a USB Thumb drive that is only capable of writing 11 MBps.

Once you know all the active storage devices that can store content, the next step is to obtain a listing of available content. This is done by obtaining an instance of the RecordingManager from the RecordingManager.getInstance() method. For OCAP platforms, this returns an org.ocap.dvr.OcapRecordingManager object (DVB platforms will return a org.dvb.tvanytime.pvr.CRIDRecordingManager).

The OcapRecordingManager has these responsibilities:

  • Managing recorded services.
  • Managing resources.
  • Scheduling recordings.
  • Resolving resource and recording conflicts.
  • Starting and stopping recordings.

The first responsibility of the OcapRecordingManager is to maintain a list of recordings (or recorded services) that can be replayed. To obtain this listing of content, you call the OcapRecordingManager.getEntries() method. This returns a RecordingList object that can be navigated with a RecordingListIterator.

When you arrive at the content you wish to play, you call the RecordingListIterator.getEntry() method to obtain a RecordingRequest object (for OCAP platforms this will be an OcapRecordingRequest). At first, it may seem confusing to have to navigate a list of RecordingRequest objects just to play content. However, DVR programming requires a change in mindset from playing traditional digital video files. Normally, in nonDVR environments, you must wait until the recording completes before you can play video files. By contrast, DVRs let you play content that is still actively being recorded. This is how DVR applications can perform trick operations such as pause, rewind, and fast-forward on live TV.

Nestled within the RecordingRequest is a RecordedService. To obtain this service, you call RecordingRequest.getService(). Once you have a RecordedService, you can play it with the Java Media Framework (JMF). Simply feed the locator returned from RecordedService.getMediaLocator() into Manager.createPlayer() and the content is presented like any other MPEG content.

While you can use traditional JMF APIs to play DVR content, you can't create a robust solution without taking advantage of OCAP's DVR-specific JMF extensions. These enhancements are defined in the org.ocap.shared.media classes and enable your applications to obtain time-shift buffer attributes, monitor timelines, and receive DVR-specific events.

Time-shift buffers are circular buffers that a DVR uses to enable trick modes (see "Inside Digital Video Recorders" DDJ, July 2005). A TimeShiftControl represents a moving window in the overall content where you can perform trick operations on live content and it offers methods to query the size and starting and ending positions of the time-shift buffer.

Timelines integrate Normal Play Times (NPT) into JMF's media time concept (that is, the playback duration of the content). An NPT is a bookmark in the content and this bookmark will be valid no matter how the content is edited. For example, in Figure 1, an application wants to display a menu on the screen exactly when the movie credits are being played (say, two hours into the movie). Even if the broadcaster inserts commercials into the content, the NPT triggers exactly when the credits are displayed (in this case, 150 minutes into the movie). When content is edited (that is, information is added or removed), an NPT discontinuity is generated and this discontinuity is represented by a single timeline. In OCAP, a JMF media time is the summation of all timelines in the content. In Figure 1, even though commercials have been added to the content, the NPT still triggers at the appropriate time.

The third JMF enhancement provided by the OCAP DVR spec are additional events and exceptions to monitor the state of the time shift and timeline attributes. For instance, if you rewind to the beginning of the content, you will receive a BeginningOfContentEvent. Similarly, if you fast forward or play past the end of the content, you'll get a RateChangeEvent. In addition, if you're playing back live content and fast forward past the end, you will not only receive a RateChangeEvent, but you may also get an EnteringLiveModeEvent (see Listing One). EnteringLiveModeEvent lets you know that you forwarded past the end of the time-shift buffer and are now displaying live video at normal speed.

Digital Video Recordings

While playback supervision is a critical element of the RecordingManager's functionality, its primary charter is to supervise recordings. The RecordingManager's responsibilities involve scheduling recordings, resource management, and resolving conflicts.

You initiate a recording by calling RecordingManager.record(). This method takes one parameter, a RecordingSpec. A RecordingSpec is an abstract base class that describes the content you wish to record. Because it's an abstract class, you must pass in a class that inherits from this class to record content. For example, if you wish to record the content that is currently being time shifted, you can use the ServiceContextRecordingSpec class. The ServiceContextRecordingSpec lets you specify when to start recording and how long to record the content. Typically, your application would call this API if the user hits the record button while watching TV.

Unfortunately, if the viewer decides to tune away from the current channel, the RecordingManager terminates any recording that was initiated by a ServiceContextRecordingSpec. If you want to ensure that your recording isn't aborted by a channel change, then you must use a ServiceRecordingSpec. A ServiceRecordingSpec lets the RecordingManager know that you want to record content associated with a specific channel (service) and is not tied to what program the viewer currently is watching at the time the recording is initiated. This type of RecordingSpec is useful when you want to schedule a recording ahead of time (say, if you want to record a specific football game or a concert).

Resource Monitor

First-generation cable and satellite DVRs had a single tuner (or source of content). This meant users couldn't watch one program while recording another or simultaneously record two programs. More modern DVRs offer at least two tuners that let viewers make two simultaneous recordings or surf on one tuner while recording on another. Alas, although a dual-tuner product has fewer recording restrictions than a single-tuner solution, there are still limitations (for instance, they aren't capable of three or more simultaneous recordings).

Thus, no matter how many tuners are in the box, users will eventually request too many recordings and something must perform arbitration (that is, an object must decide which recording requests will be accepted or rejected based on hardware resources). This conflict resolution process is very network specific and consequently, it is not defined in org.ocap.dvr.shared. Rather, in an OCAP DVR, the OcapRecordingManager cooperates with the Multiple Service Operator-specific monitor app to resolve conflicts.

Recall that in "The OpenCable Application Platform" (DDJ, June 2004), I mentioned the monitor application has access to privileged network resources and is responsible for resolving all resource conflicts on the platform. The OCAP DVR spec extends the monitor application's responsibilities to include resolution of DVR resource conflicts. For instance, if users have scheduled two recordings at 8:00 pm and an Emergency Alert System (EAS) is broadcast at 8:02 pm, the OcapRecordingManager alerts the monitor application of the conflict and the monitor application would then abort the lower priority recording to ensure that the EAS broadcast has access to the tuner so that the emergency alert could be broadcast.

Conclusion

The OpenCable Application Platform has long promised that it would break the stranglehold that proprietary platforms have on the U.S. cable market. However, since it didn't offer the DVR capabilities that viewers crave, cable companies have been forced to use proprietary DVR solutions to satisfy consumer demand. Thankfully, the release of the OCAP Digital Video Record specification removes the last hindrance to widespread acceptance of OCAP. Finally we will be able to write Java applications to time-shift DVR content, record our favorite TV programs, and play these programs back with trick controls. Clearly, the release of this specification and boxes that will soon follow is a significant milestone in the evolution of interactive television.

DDJ



Listing One

import org.ocap.shared.media;
import org.ocap.dvr;

   // sample controllerUpdate() processing for DVR applications
   //
   // All JMF applications implement a controllerUpdate() method
   // The OCAP DVR specification adds new events that DVR applications
   // should listen to.  In this illustration, the listener
   // monitors EnteringLiveModeEvent
   
   public synchronized void controllerUpdate(ControllerEvent event) 
   {
     // this event will be received when the DVR JMF player is playing live 
     // content from a tuner. Typically, this event will be received when 
     // the user does a trick operation (such as a fast forward) that causes 
     // the player to run out of recorded digital video and automatically 
     // start playing live content.
     if (event instanceof EnteringLiveModeEvent) 
     {
       // your application work would be done here...
     }
     // this event will be received when the DVR JMF player is
     // playing is playing recorded content.  This typically
     // is generated when the application performs a trick operation
     // (i.e. pause or rewind) on live content.

     else if (event instanceof LeavingLiveModeEvent) 
     {
       // your application work would be done here...
     }
   }
Back to article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video