Exporting Movies to Any Installed Format

Exporting to a list of known formats is limiting—if the end user has installed new movie exporters, either from third parties or via an update to QuickTime itself, a program that uses a canned list of exporters won’t be able to pick them up. Fortunately, QuickTime provides a means of querying for installed components of a given type. You can use this strategy to offer a list of all available exporters.

How do I do that?

The AdvancedMovieExport eliminates the three canned entries in the choices array that were used by SimpleMovieExport (shown in Example 4-2) and instead builds the array through a process of discovery; this code would replace the short “build choices” block in the constructor for SimpleMovieExport but needs to go inside the try-catch, because it makes calls that can throw QTException:

Vector choices = new Vector( );
ComponentIdentifier ci = null;
ComponentDescription cd =
  new ComponentDescription(StdQTConstants.movieExportType);
while ( (ci = ComponentIdentifier.find(ci, cd)) != null) {
  // check to see that the movie can be exported
  // with this component (this throws some obnoxious
  // exceptions, maybe a bit expensive?)
  try {
      MovieExporter exporter = new MovieExporter (ci);
      if (exporter.validate (movie, null)) {
          ExportChoice choice =
              new ExportChoice (ci.getInfo( ).getName( ),
                                ci);
          choices.addElement(choice);
      }
  } catch (StdQTException expE) {
      System.out.println ("** can't validate " +
                          ci.getInfo( ).getName( ) + " **");

Note

Run this example with ant run-ch04-advancedmovieexport.

      // expE.printStackTrace( );
  } // ow!
}

When run, the list of supported exporters is surprisingly large, as seen in Figure 4-5. In this case, a “normal” movie, consisting of a video track and an audio track, is being exported, meaning that any audio-only format (Wave, AIFF, etc.) or audio/video format (QuickTime, AVI, MPEG-4, etc.) will work.

Discovered Movie Exporters

Figure 4-5. Discovered Movie Exporters

Note

Hinted Movie, the format selected in Figure 4-5, is a QuickTime movie with “hints” to optimize streaming.

You also should take note of the discovered exporters that cannot export the movie. These are logged to standard out:

run-ch04-advancedmovieexport:
   [java] ** can't validate BMP **
   [java] ** can't validate Standard MIDI **
   [java] ** can't validate Picture **
   [java] ** can't validate Text **
   [java] ** can't validate QuickTime TeXML **
   [java] ** can't validate QuickTime Media Link **

These fail because the source movie doesn’t contain tracks that can be exported to these formats. With a source movie with different kinds of tracks, some of these would succeed and others would fail.

What just happened?

The process of discovering components by subtype is rather peculiar. It hinges on making repeated calls to a “find” method, passing in the last matching component. Doing this requires a ComponentDescription , used as a template to match against, and a ComponentIdentifier, which refers to a specific component (though not a specific instance of that component). To find movie exporters, initialize a ComponentDescription template with the constant movieExporterType.

The static ComponentIdentifier.find() method finds matching components, but instead of offering an array or other collection of matches, it requires you to repeatedly pass in the ComponentDescription template, along with the previous ComponentIdentifier found by the method. For the first iteration, this will be null. The find( ) call returns a ComponentIdentifier, which you pass to the MovieExporter constructor to create a new exporter. When find( ) returns null, there are no more matches.

Note

Yes, this is totally weird, at least from a Java perspective.

The matched ComponentIdentifier provides information about itself via the getInfo( ) method. This returns another ComponentDescription object, different from the one used as a template. You can use this to get type and subtype information (as FOUR_CHAR_CODE ints, of course), a name, an information String, a manufacturer code, etc.

Finding a MovieExporter is no guarantee that it actually will work. You can call validate( ), as this example does, to check that the instantiated exporter can do an export from the given movie. In this example, if validate throws an exception, it’s logged to standard out and the exporter is not added to the JComboBox.

What about...

...setting the export parameters programmatically, instead of using the export dialog every time? This is possible, although it will require using the export dialog at least once in development. A configured MovieExporter can return its configured state in the form of an AtomContainer object, by way of the getExportSettingsFromAtomContainer() method. This object can be passed to an exporter via the setExportSettingsFromAtomContainer() method.

Note

"Atoms” are a low-level data structure that do almost all of QuickTime’s heavy lifting. Application-level code uses them only for really advanced stuff (see Chapter 9).

Within a single running application, this is pretty straightforward. To persist between sessions, you must save off the native structure by calling getBytes( ) on the AtomContainer and then persist it to disk, database, etc. To recreate the settings in the future, read the bytes into a byte array, create a QTHandle from the array, and then pass that to AtomContainer.fromQTHandle( ) to create the AtomContainer.

QuickTime 6.3 introduced a new API for setting exporters programmatically, but as of this writing, it has not been exposed via QTJ method calls.

Also, if I specify type and subtype, will I always get one match? No, in some cases, you’ll get multiple matching components, and you might need to use other criteria to pick which one to use. In a rather infamous case pointed out by one of my tech reviewers:

Sometimes you get more than one exporter with the same subtype and need to use the “manufacturer” code to distinguish them. This applies particularly to AIFF exporters—the first exporter you find of that type only exports MIDI. To export an arbitrary QT audio file to AIFF you need to explicitly iterate and pick the second one!

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.