QuickTime for Java: A Developer's Notebook/Preface
Java has been a huge success in many fields—distributed enterprise applications, mobile phones, web applications—but one field that it has clearly flopped in is media. A sound API, javax.sound, suffices for simple playback and mixing of a handful of old formats, and was added to the Java core (the classes any Java runtime must include) in Java 2 Standard Edition (J2SE) 1.3. The optional package for media, Java Media Framework (JMF), fared much worse. After two releases, a 1.0 that provided only playback and a 2.0 that added streaming, transcoding, and some lower-level access, the product was slipped into maintenance mode and has seen little attention since 1999. In fact, the most monumental change to JMF in this time was the loss of a feature: MP3 support was removed in 2002, due to licensing concerns. Making things worse, JMF's all-Java version had weak support for popular formats and codecs. Native editions could play more media, but Sun initially created versions only for Windows and Solaris, later providing minimal support to a third-party Linux port and absolutely no support for a Mac version. Setting aside the dubious premise of Solaris as a media production OS, this effectively made JMF practical only on Windows, eliminating Java's cross-platform advantage.
Enter QuickTime, a multimedia framework originally introduced by Apple for the ("Classic") Mac OS in late 1991. QuickTime defines both a file format (the QuickTime .mov format) and many APIs for working with time-based media. The provided functions allow applications to create media (either synthetically or via capture), manipulate it, and present it. Media types supported by QuickTime include sound and video, timed text (captions), graphics, interactivity, and a panoramic-image style of virtual reality (VR).
Unfortunately, despite having an industry-leading multimedia framework, in 1998 there was no straightforward means of exposing QuickTime to Java developers. And whereas most APIs start with an interface and then gain a reference implementation, Apple had an implementation and the native QuickTime libraries, but no Java interface. Compounding the problem, QuickTime was designed to be called from C (sometimes called "straight C" or "procedural C") and thus lacked the object orientation a Java interface would call for.
Apple's "Biscotti" project took a remarkable approach to this problem—not only did the Biscotti designers provide a Java layer to make QuickTime calls, but they also fashioned an object-oriented API out of a non-OO framework. It helps that QuickTime is made up of a number of fairly elaborate structures, along with functions that work with them. The Biscotti designers saw that these structures could be combined into Java objects. For example, they took the Movie struct and many of the functions that worked with a movie, and fashioned these into the quicktime.std.Movie class. Functions such as StartMovie( ), StopMovie( ), CopyMovieSelection( ), and PasteMovieSelection( ) became the Java instance methods start( ), stop( ), copySelection( ), and pasteSelection( ), respectively. Biscotti, now known as QuickTime for Java, still has its quirks, but it's a lot more Java-like than some other "wrapper" frameworks for Java.
By comparison, the JOGL API, which offers a Java wrapper to the OpenGL graphics library, simply dumps the functions defined in the C header files into pseudo-objects with upward of 2,000 methods each!
Whatever Apple's reasons for creating QuickTime for Java (QTJ), the application has been the beneficiary of many fortuitous advances. The most significant comes from QTJ's nature as a Java wrapper around a native framework: as the native QuickTime grows, so does QTJ. In particular, when QuickTime supports a new format or codec, it is almost always available to QTJ immediately, without requiring any new QTJ development. When QuickTime added MPEG-4 support, QTJ picked it up for free. When Apple started selling songs on the iTunes Music Store, QTJ was able to play the encrypted AAC audio files right away.
Why a QuickTime for Java Book?
The strangest thing about QuickTime for Java might be that if you read Apple's documentation, you get the idea that it was originally aimed not at Java developers, but at QuickTime developers. One of the introductory docs, "Summary of QuickTime for Java," says as much: "QuickTime for Java came about to meet developers' need for a way to get at QuickTime besides using C calls." It then goes on to define Java concepts like classes, objects, and instance methods...it even has a gentle introduction to the idea of garbage collection.
To a Java developer, this seems wildly backward. The Java developer, evaluating QTJ as a multimedia toolkit, already knows about garbage collection, and instead he needs an introduction to the QuickTime concepts that are taken for granted: the idea of the movie as an "organizing principle" rather than an explicit media stream, the relationship of movies, tracks, and media, and odd legacies left over from the old Mac OS. The existing documentation doesn't help much—the Javadoc for a given method often gives a one-line description (at best), followed by a reference to the underlying C function it calls.
The goal of this book is to offer a guide to QTJ from a Java point of view. That means introducing QuickTime concepts as necessary, treating it as essentially new material. Hopefully, this will present QTJ as an end in itself, meaning you can write effective QTJ applications without having to understand the native QuickTime API or constantly consult its documentation. It also means that as a book for Java developers, we'll always adhere to Java coding conventions, taking particular care to note where QTJ's way of doing something might not seem "normal" from a Java perspective.
Assumptions and Definitions
This book assumes that you are comfortable with Java 2 Standard Edition, Version 1.4 (J2SE 1.4). You should understand the core language and packages, particularly AWT and Swing. I use both AWT and Swing extensively—sometimes in the same example, when it's clearer to do it that way—AWT is much faster, but Swing has some space-saving conveniences that keep the examples short and focused.
If you don't think AWT is overly verbose, try building a choice dialog sometime.
You should also have at least a passing familiarity with concepts of digital media. Although the Developer's Notebooks aren't about theory, there are a few terms you should know off the bat.
- In QuickTime, a "movie" isn't just an audio/video file—it is an organization of media elements that can include audio, graphics, video, text, interactivity, etc. For the purposes of this book, anything that can be represented by the Movie class is a "movie," including remote MP3 streams, wired-sprite video games, etc.
- A codec is a piece of code that can encode and/or decode media in a given format. Apple's documentation often breaks this down into media handlers , which understand a given encoding, and compressors and decompressors to compress or extract data.
- Container format
- File formats like QuickTime .mov or Microsoft's AVI are containers that can hold different kinds of content, such as a combination of audio, video, or other kinds of media. Note that parsing the format and parsing its contents are two separate things: QuickTime can handle the format of a given AVI file but might not support a codec used in it (and vice versa for libraries that support the QuickTime file format). Also, a container like QuickTime can refer to remote data, such as media in another file or out on the network, so a given .mov file does not necessarily contain all the media needed to play the movie.
This book is organized into chapters of related material, but as you'll see, this is no "animal book," nor is it an Inside Macintosh, for that matter. Each chapter is broken down into tasks, most of which can be understood fairly independently. In some cases, a chapter will start off with a complete running application, like the movie player in Chapter 2 or the editor in Chapter 3, then gradually add features (undo, redo, save, etc.) in successive tasks by indicating only what new code needs to be added to implement the feature. The only exception is a startup/teardown convenience class, QTSessionCheck, introduced in Chapter 1 and used by nearly all the other examples as a means of reducing distracting boilerplate code throughout the book.
Each task exists as a complete example in the downloadable sample code, which is hosted at http://www.oreilly.com/catalog/quicktimejvaadn.
About the Examples
When unzipped, the examples will create a directory whose contents look like this:
build.xml my.ant.properties.win classes/ src/ jars/
build.xml is the build file for Ant, the de facto standard for building Java projects. You don't have to use Ant, but considering the classpath challenges in dealing with Java builds, particularly with QTJ (see Chapter 1), you'll probably find it well worth your while. If you don't already have it, you can get Ant from http://ant.apache.org/, and you can learn more in Ant: The Definitive Guide (O'Reilly).
The classes and jars directories are created by Ant, and will not be present when you first unzip the archive.
Using the command line, type ant in this directory to run the default target. In this case, it's the help message:
cadamson% ant Buildfile: build.xml help: [echo] Available targets: [echo] ch0n -- compile source for chapter n (eg "ch01", "ch02", etc.) [echo] all -- compile source for all chapters [echo] ch0n.jar -- make a .jar file for chapter n [echo] qtj-notebook.jar -- compile source for all chapters and make jar [echo] all.jar -- synonym for qtj-notebook.jar [echo] run-example -- compile and run "example" [echo] help-names -- echo all example names for use with run-example [echo] clean -- remove .class files [echo] help -- this help message (default) [echo] BUILD SUCCESSFUL Total time: 2 seconds
You can look in the build.xml file for more information. One important note is that compiling requires the path to the QTJava.zip file, as described in Chapter 1. The default is the Mac OS X path, /System/Library/Java/Extensions/QTJava.zip. If you're using Windows, you need to override this. The provided file my.ant.properties.win has a sample path that looks like this:
Edit this so that it refers to the path to QTJava.zip on your system, and then rename the file to my.ant.properties, so build.xml will pick it up. Because any Ant properties are picked up from this file, it also gives you the opportunity to make other Ant tweaks, such as repointing jvm.home to use one of several Java installations on your box, or to change the java.compiler to jikes.
To compile all the book examples into a JAR file, type:
This will produce output like the following:
cadamson% ant qtj-notebook.jar Buildfile: build.xml init: [echo] qtjavazip.file = /System/Library/Java/Extensions/QTJava.zip all: [javac] Compiling 53 source files to /Users/cadamson/Documents/ O'Reilly/books/qtj developer's notebook/code/classes qtj-notebook.jar: [jar] Building jar: /Users/cadamson/Documents/O'Reilly/books/qtj developer's notebook/code/jars/qtj-notebook.jar BUILD SUCCESSFUL Total time: 7 seconds
You can then run any of the examples by extending the classpath to include the qtj-notebook.jar file, as in:
java -cp jars/qtj-notebook.jar com.oreilly.qtjnotebook.ch02.SimpleQTPlayer
There are also Ant targets to compile and run every example in the book. Use ant help-examples to see a list of example names.
Conventions Used in This Book
The following typographical conventions are used in this book.
- Plain text
- Indicates menu titles, menu options, menu buttons, and keyboard accelerators (such as Alt and Ctrl).
- Indicates new terms, URLs, email addresses, filenames, file extensions, pathnames, directories, and Unix utilities.
- Constant width
- Indicates commands, options, switches, variables, attributes, keys, functions, types, classes, namespaces, methods, modules, properties, parameters, values, objects, events, event handlers, XML tags, HTML tags, macros, the contents of files, or the output from commands.
- Constant width bold
- Shows commands or other text that should be typed literally by the user.
- Constant width italic
- Shows text that should be replaced with user-supplied values.
This icon signifies a tip, suggestion, or general note.
This icon indicates a warning or caution.
This icon indicates a Developer's Note.
Using Code Examples
This book is here to help you get your job done. In general, you may use the code in this book in your programs and documentation. You do not need to contact us for permission unless you're reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing a CD-ROM of examples from O'Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product's documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: "QuickTime for Java: A Developer's Notebook by Chris Adamson. Copyright 2005 O'Reilly Media, Inc., 0-596-00822-8."
If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at email@example.com.
How to Contact Us
Please address comments and questions concerning this book to the publisher:
O'Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
(800) 998-9938 (in the United States or Canada)
(707) 829-0515 (international or local)
(707) 829-0104 (fax)
We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at:
To comment or ask technical questions about this book, send email to:
For more information about our books, conferences, Resource Centers, and the O'Reilly Network, see our web site at:
When you see a Safari® enabled icon on the cover of your favorite technology book that means the book is available online through the O'Reilly Network Safari Bookshelf. Safari offers a solution that's better than e-books. It's a virtual library that lets you easily search thousands of top tech books, cut and paste code samples, download chapters, and find quick answers when you need the most accurate, current information. Try it for free at http://safari.oreilly.com.
Brett McLaughlin deserves huge thanks for getting this book to you. Not only is he the creator of the Developer's Notebook series and the editor of this book, but he also saw that QuickTime for Java was a topic whose need for practical know-how (to navigate the media jargon, obtuse concepts, and teeming "gotchas") was well-suited for this series. Chuck Toporek at O'Reilly was also very helpful in getting people excited about the book. And, of course, I wouldn't even be writing for O'Reilly if I hadn't bumped into Daniel Steinberg at the Mac OS X conference a few years ago, which ultimately led to our working together to edit the ONJava and java.net web sites.
The members of the quicktime-java and quicktime-api mailing lists, and the OpenQTJ project at java.net, have also been extremely helpful in working through problematic material and passing along those nuggets of knowledge that you're somehow "just supposed to know." In particular, the material in Chapter 6 about working around the incomplete state of video capture came in many ways from bits of discussion here and there saying, "you can get it to work by passing in your own GWorld." After I posted an early version of this book's "motion detector" example, some quicktime-java members developed it further into a more general-purpose capture preview. Tech reviewers Rolf Howarth, Anthony "aNt" Rogers, Dmitry Markman, and Sean Gilligan have also been generous with their time, attention, and knowledge, and have made this a far better book than it would have been without them.
I couldn't contact my friends on the QuickTime team while working on this book—another publisher has exclusive access to those developers for QuickTime titles—so they were probably wondering where I was while this book was in silent running. But they've been very supportive in the past and I'm looking forward to being able to work with them again.
I wouldn't even have a programming career if Tammie Childs at Pathfire hadn't taken a chance on me when all I had to speak of for my programming skills were a couple of crazy applets. She also took me back in when Piece Of Crap Wireless Companies No.s 1 and 2 crashed and burned, and still encouraged me to pursue my interests when articles led to editing and then to books.
Finally, I want to thank my wife Kelly, and our son Keagan, for being supportive while I took a big chance on writing a book, and for cutting Daddy some slack when he needed to go downstairs and do more writing. I hope that Keagan hasn't picked up the more extreme expressions that I emitted while working through some of the less stable parts of QuickTime for Java. By the way, you'll notice that Keagan is all over this book for two reasons: first, I don't have to pay license fees on media I own, such as my own iMovies, and second, he's quite cute.
Obligatory O'Reilly music check: this time it was Roxy Music, the Kinks, Nellie McKay, Elvis Costello, Thelonious Monk, a bunch of anime soundtracks (notably .hack//SIGN, Nadia, FLCL, and Cowboy Bebop), and the streaming audio stations Radio Dupree, Armitage's Dimension, and Gamer Girl Radio.