Chapter 4. Working with Components

When QuickTime came out in 1990, it could play movies the size of a postage stamp—barely—on $7,000 hardware. It used audio and video codecs that, although still supported today, have long since been abandoned by users. Yet it’s been a smooth transition from Apple Video to Cinepak to MPEG-4. This is thanks to an extraordinarily modular design—most of the heavy lifting in QuickTime is performed by components , or shared code fragments that can be discovered and used dynamically. Components provide support for importing and exporting image and movie formats, performing image and sound compression and decompression, accessing system resources, and much more. The QuickTime installer provides components for many features, and components added later by the end user, from either Apple or third parties, can provide more functionality, like support for more media formats.

Components aren’t always front-and-center in the API—after all, the first few chapters have managed to avoid mentioning them entirely. QuickTime has been assumed to just “do the right thing” when it comes to opening files and turning them into movies, decompressing and rendering the data, saving it to disk, etc. When needed, QuickTime looks through its catalog of components for required functionality and gets what it needs.

But sometimes it’s desirable or necessary for the developer to work with components more directly, to figure out what’s available or to specify behavior. Figuring out what tools are available at runtime can be a powerful asset.

Specifying a Component’s Type

In QuickTime, components are identified by a type and a subtype . The type specifies a broad area of functionality, while the subtype is a specific implementation of that functionality. For example, there’s a “movie exporter” type, which identifies components that can write a movie into a non-QuickTime format, with subtypes identifying the exporters for AVI, MPEG-4, etc.

These identifiers are 32-bit int values, but typically they’re not enumerated constants like you might expect from Java. Usually, the 32 bits are read as four 8-bit ASCII characters, making a short, human-readable name. These are defined in the native API as OSTypes, but when populated with meaningful values, they’re called "four character codes,” from the native FOUR_CHAR_CODE function that returns an OSType for a string. This often is abbreviated as FCC, or 4CC.

The scheme makes a lot of sense from the C programmer’s point of view. For example, defining the 4CC for a movie requires a nice, simple one-liner, as seen in the native Movies.h header file:

MovieResourceType = 'moov'

Note

"moov” shows up a lot in QuickTime: as an identifier for a movie’s copy-and-paste type, as its Carbon file type, as the top-level “atom” in the file format, etc. Say it out loud if you don’t get the joke: moo-vee.

It turns out that dealing with 4CCs is harder in Java, thanks to Java’s more modern approach to text. Specifically, the use of Unicode means Java characters are 2 bytes each, which means help is needed to turn a Java string into a 4CC.

How do I do that?

Fortunately, the QTUtils class provides two methods for converting to and from 4CCs: toOSType() and fromOSType( ). Example 4-1 exercises these methods by converting a Java string to and from its 4CC representation.

Note

Compile and run this example from the downloaded book code with ant run-ch04-fourcharcodetest.

Example 4-1. Converting to and from FOUR_CHAR_CODEs

package com.oreilly.qtjnotebook.ch04;
 
import quicktime.util.QTUtils;
 
public class FourCharCodeTest extends Object {
 
  public static void main (String[  ] args) {
      if (args.length < 1) {
          System.out.println ("Usage: FourCharCodeTest <fcc>");
          return;
      }
      System.out.println (args[0]);
      int fcc = QTUtils.toOSType (args[0]);
      System.out.println (fcc);
      System.out.println (Integer.toHexString (fcc));
      String fccString = QTUtils.fromOSType(fcc);
      System.out.println (fccString);
  }
 
}

The main( ) method takes a String from the command line, converts it to a 4CC, prints that value in decimal and hex, then converts it back to a String. When it’s run with moov as an argument, the output looks like this:

cadamson% java -classpath classes 
  com.oreilly.qtjnotebook.ch04.FourCharCodeTest moov
moov
1836019574
6d6f6f76
moov

Note

Really hard-core QuickTime developers can read 4CCs in hex without thinking about it. Drop a movie file on a hex editor and you’ll probably see 6d6f6f76 (moov) as bytes 4-8.

What just happened?

These utility methods provide some good, old-fashioned bit-munging to do their conversions. toOSType( ) takes a String as its argument, grabbing the low 8 bits of each character and putting them in the proper place in the returned int. In other words, the bottom 8 bits of the first character take up the first 8 bits of the int, then the next character is used for the next 8 bits, and so on. Figure 4-1 shows where the bits end up in the bit-shifted "moov“.

Bit-wise, hex, and character representation of a FOUR_CHAR_CODE

Figure 4-1. Bit-wise, hex, and character representation of a FOUR_CHAR_CODE

fromOSType( ) does the opposite conversion, masking off the bits of an int and returning a four-character Java string.

Get QuickTime for Java: A Developer's Notebook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.