MHP has two APIs that can be used for controlling the display of video signals and choosing which signals to actually present to the user. The first of these is the Java Media Framework (JMF), with a few modifications and a lot of extensions. This is mainly used for controlling individual media clips.
The second API that we have is the JavaTV service selection API. This is designed to let applications switch entire services, so using it to manipulate a video or audio stream is a little like using a sledgehammer to crack a nut, and is equally dangerous. Using this API involves a very real risk that you application may not survive the experience.
Finally, and only tangentially related to media presentation is the tuning API. The tuning API provides applications with a way to access another transport stream, mainly so that an application can access data-only services that are on a different transport stream.
Locators, more locators, and yet more locators
Before we start looking at how we can manipulate and control media in MHP, there’s one important topic that needs covering first – how do we refer to that media?
Most of the APIs for playing media or referring to transport streams or services use a concept called a locator to refer to a particular piece of media. Locators are opaque objects that do not directly expose their reference to the content. Internally, these references may be pointers, numbers or anything else that the implementation wishes to use. However, all locators have a human-readable format (an external form) that can be used, and it’s probably no surprise that this format is a URL. Of course, a new URL format had to be defined for referring to DVB services, and we’ll see what this looks like below.
Why do we need a locator if it’s simply defining a new URL format? Mainly because the java.net.URL class is declared as final, which means that it can’t be extended. This would not be such a problem if it weren’t for the semantics of the class as it currently stands, which are really only applicable to IP-based connections. For this reason, various groups have needed to provide their own representation of something that is basically a URL, because they have no other choice. This big problem is that since so many groups have needed this kind of functionality, several different families of locator have been created over the years. These can be split into three main class hierarchies: javax.media.MediaLocator
and subclasses, javax.tv.locator.Locator
(which currently has no subclasses) and org.davic.net.Locator
and its subclasses.
The full list of locator classes is as follows:
javax.media.MediaLocator
org.davic.media.MediaLocator
javax.tv.locator.Locator
org.davic.net.Locator
org.davic.net.dvb.DvbLocator
org.davic.net.dvb.DvbNetworkBoundLocator
org.dvb.locator.FrequencyLocator
(added in MHP 1.1.2)org.dvb.locator.NetworkInterfaceBoundMediaLocator
(added in MHP 1.1.2)
These are all used in subtly different ways. For instance, a javax.media.MediaLocator
is used by the Java Media Framework to refer to a media clip that will be presented, and so this may refer to either a DVB service or service component, an audio clip, or a video drip. A NetworkInterfaceBoundMediaLocator
is simply a MediaLocator that refers to a piece of content on a specific tuner.
org.davic.net.Locator
and its subclasses are designed to refer to transport streams or services, with org.davic.net.dvb.DvbLocator
referring specifically to transport streams and services in a DVB network. FrequencyLocator
objects were introducted in MHP 1.1.2 to provide a way of referring to services that are carried in transport streams which have no service information. Other standards such as OCAP have extended the org.davic.net.Locator
class in their own way to create locator classes that are compatible with the standards that they use, and so these introduce yet more classes into the mix.
Given these different hierarchies of locators, there is a very real danger that using them in applications will be both complex and error-prone. To help avoid this, the MHP standard mandates that some of these otherwise-unrelated classes will be related. For instance, MHP specifies that the org.davic.net.Locator
class will implement the javax.tv.locator.Locator
interface and that any instances of javax.tv.locator.Locator
in an MHP environment will actually be instances of org.davic.net.Locator
. Furthermore, it specifies that any instances of org.davic.net.Locator
in an MHP system will actually be instances of org.davic.net.dvb.DvbLocator
, and so this removes a great deal of complexity from the use of locators in MHP. JavaTV and DAVIC locators can be used interchangeably, leaving only JMF MediaLocator
objects out of the picture.
MediaLocators are taken care of via the org.davic.media.MediaLocator
class. While this is not related to org.davic.net.Locator
via inheritance, it does include a constructor that takes an org.davic.net.Locator
as an argument. This allows applications to create MediaLocator
objects directly from other locators, and thus integrates all of the different locator classes. It is not possible to convert from a MediaLocator
to an org.davic.net.Locator
object (or to construct one directly from the other), this can be accomplished by using the external form of the MediaLocator
to create an org.davic.net.Locator
.
The diagram below shows the relationship between the different locator classes in an MHP implementation:
For those of you who want to learn more about exactly how the relationships between the different locator formats affects a specific API, section 11.11 of the MHP specification goes into much more detail about what locator types are accepted by which APIs in an MHP system.
Creating locators
Some of these locator types (javax.media.MediaLocator
, org.davic.net.Locator
and their subclasses) can be created directly from a URL. The org.davic.net.Locator
class also has a number of other constructors that allow the various components of the locator to be specified directly. The exact nature of these components, and the URL formats for these locators are introduced in the next section. org.dvb.locator.NetworkInterfaceBoundMediaLocator
is a slightly special case, in that it is created from an existing MediaLocator
(as well as a reference to an org.davic.net.tuning.NetworkInterface
object) rather than directly from a string.
Instances of javax.tv.locator.Locator
, on the other hand, can only be created by using the javax.tv.locator.LocatorFactory
class. This factory class provides the createLocator()
method, which takes a URL of the same format as the previous locator classes. Since org.davic.net.Locator
implements the javax.tv.locator.Locator
interface in an MHP system, this means that MHP or OCAP applications can create a JavaTV locator in the same way that they can create a DAVIC locator, and vice versa.
FrequencyLocator
objects are even more exotic. Since these can not rely on service information to help them find the service that they refer to, defining a standard URL format that works on all transmission mechanisms is tricky. To solve this, the constructor for a FrequencyLocator
takes two arguments: a binary representation of the delivery system descriptor for the transport stream containing the service (taken from the NIT) and a program number for the service within that transport stream. This may seem complex, but this is the most flexible way of referring to a program in a transport stream that contains no service information.
Content Formats in MHP
The media-related APIs in MHP refer to three main content formats. This section will hopefully give you a little insight into them, since they are quite different from the content formats that you may be familiar with. It’s important to remember, however, that many APIs will only be able to accept locators to some of these content formats – usually DVB services. Only the Java Media Framework can handle all of the content formats that are listed here.
DVB services or service components
Many of the APIs in MHP refer to DVB services. As we’re already pretty familiar with the format of DVB services, we’ll concentrate here on the DVB locator format. Locators that refer to DVB services are created using the DVB URL format:
dvb://<onID>.<tsID>.<sID>[.<ctag>[&<ctag>]][;<evID>][<path>]
Where the various parts of the URL are as follows:
- onID
- The Original Network ID, which identifies the broadcaster or network that produced the content (not the network currently broadcasting it, if they are different)
- tsID
- The Transport Stream ID, which identifies a specific transport stream that the network is broadcasting
- sID
- The Service ID, which refers to a service within that transport stream
- ctag
- The Component Tag, which refers to a specific elementary stream that has been tagged in the service information
- evID
- The Event ID, which identifies a specific event that is part of the service
- path
- The path to a file in a broadcast filesystem that’s being transmitted on that elementary stream
All of these components (except for the path component) are represented as hexadecimal values without the leading 0x
. The path component uses the standard URL path format as defined in RFC 2396. All of the numeric identifiers used for the various components of the URL match the identifiers used in the DVB service information that is part of the transport stream.
Some example DVB URLs are:
dvb://123.456.789
(identifies a DVB service)
dvb://123.456.789;42
(identifies a DVB event)
dvb://123.456.789/images/logo.gif
(identifies a file in an object carousel)
dvb://123.456.789.66
(identifies an elementary stream within a service using its component tag)
As we can see, only the first three elements are required. This means that a DVB URL will always refer to a service, although in some cases (most notably the org.davic.net.dvb.DvbLocator
class when used in certain APIs) it is possible that the service ID will be ignored and that a locator created from the URL will refer to a transport stream. The tuning API is the case where this is most obvious.
In the third case, the locator refers to a file in an object carousel, but the carousel in question isn’t specified. In this case, the carousel that will be used is the default carousel. It isn’t specified anywhere which carousel is the ‘default ‘ one, however, so generally it’s best to avoid using this type of locator. There aren’t many cases where it’s necessary, and so it’s (luckily) not commonly used.
DVB URLs that refer to files in an object carousel may also be used to refer to MPEG audio clips.
In MHP 1.1.2, it is also possible to refer to a DTV service in a transport stream that does not contain service information using the org.dvb.locator.FrequencyLocator
class. This does not have a standardized URL representation, and instances of this class can not be created using a simple URL string.
MPEG audio clips
This content type is pretty straightforward, and should be familiar to most developers. It’s simply a piece of MPEG-1 audio that is loaded from a file. This file will typically be stored in a DSM-CC object carousel.
Applications can use a standard file://
URL to refer to the clip – this makes things slightly simpler conceptually, but it does mean that the clip must reside on a DSM-CC object carousel that the receiver is already connected to. Alternatively, applications may use a dvb://
URL to refer to the clip, but this is less common.
Finding the full path of a file://
URL is not easy, since the mount point for an object carousel is platform-dependent. In order to successfully (and interoperably) find the correct URL for a file in an object carousel, it’s necessary to get this from the file itself:
// Create a DSMCC object that refers to the file in the // carousel. Note that this is a relative path name // (relative to the application's root directory, // usually). In this case, it's an MPEG audio file. DSMCCObject myDsmccObject; myDsmccObject = new DSMCCObject( "my/file/path/filename.mpg"); // We can call getURL() on that object to get a file:// // URL that points to it URL url = myDsmccObject.getURL() // Now we can create the Locator try { LocatorFactory locatorFactory = LocatorFactory.getInstance(); Locator myLocator; myLocator = locatorFactory.createLocator( url.toString()); } catch (MalformedLocatorException e) { // Catch the exception in whatever way we see fit. // Since we should always get a valid URL from // getURL(), this exception should not get thrown in // this situation. }
Video ‘drips’
This is a new content format that’s pretty much unique to the digital TV world. The main aim of this format is to provide a memory-efficient way for displaying several similar images. Basically, it is a very short piece of MPEG-2 – the first thing in the file is an MPEG-2 I frame that can be decoded and presented to the user. This is followed by one or more P frames, which are then decoded based on the preceding I frame. This allows the decoder to update a static image in a very memory-efficient way.
In this format, the data is passed to the Java Media Framework via an array of bytes, so the content is already loaded from a file or other data source. Because of this, the format doesn’t really have a locator that identifies the place the data is loaded from. A URL is still needed, though, to create locators and create the appropriate objects to decode this content format. For this reason, the entire URL, for every piece of video ‘drip’ content is
dripfeed://
Believe it or not, this is a valid URL, and this tells the locator what the content format is, but without needing to refer to a specific piece of data. We’ll see more about how this works in the next section.
Locators and their external form
As we’ve already seen, locators have an external form that is a URL. However, there is a complication with external forms that may not be obvious at first, especially if you haven’t read the MHP specification very carefully. Let’s look at the following code sample:
org.davic.net.dvb.DvbLocator myLocator; myLocator = new org.davic.net.dvb.DvbLocator( "dvb://1.2.3"); System.out.println(myLocator.toExternalForm());
What result will be printed? Not what you may expect. Instead of the string "dvb://1.2.3", you may see something different: the string "dvb://1..3". Why?
Version 1.0.2 and 1.1 of the MHP specification (as well as earlier versions) say that only instances of org.davic.net.DvbNetworkBoundLocator
and its subclasses will return the full URL (including the transport stream ID) as their external form. Other versions of the org.davic.net.dvb.DvbLocator
class will return the URL without the transport stream ID.
Version 1.0.3 removes this clause, and so in implementations that comply with version 1.0.3 the locator that is returned will contain the transport stream ID.