QuickTime • 1:07:54
This session shows application developers how to take their media capabilities to new and exciting levels using the APIs built into QuickTime 6. Also covered are a host of new tips and tricks for using QuickTime APIs in Cocoa and in Java.
Speaker: Kevin Calhoun
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
So in this session today, we're going to cover some of the new things in QuickTime's APIs. We're also going to talk about the basics of QuickTime, what you can do with QuickTime in your application. As you already know, QuickTime offers for your application the ability to play back media, the ability to capture media from the analog world or from the digital world.
It offers you the ability to create content inside of your applications, even to create content from your documents that you might not consider as having anything to do with video or anything to do with audio, and we'll show you some of that today. You have the ability, of course, to edit already created content in your applications. And finally, QuickTime offers you the ability to create content from your applications. It also offers you an ability to deliver media out to the world.
Did we mention something about the 100 million downloads of QuickTime 6 today? Also the fact that our plug-in for browsers is well integrated with browsers. All the browsers that we support, it's about this long. We have the ability to deliver media via people's .Mac accounts. We have the ability to stream media, and there was something about 100 million downloads of QuickTime 6 since it was first introduced as well, I think I might have mentioned. So anyway, you have no problem delivering QuickTime media to the world. world.
One of the topics we're going to cover today is QuickTime's platform citizenship. What does this mean? As you may know, QuickTime's native platform was the classic Mac OS. It originally shipped, I think, at the beginning of 1991. Someone will correct me if I'm wrong. And at that time, the current Mac OS was System 7. We ran on System 6 at that time as well.
And some things have changed, one or two, in the ensuing years. We're going to talk here at this session about how good a citizen QuickTime is on today's platforms. And as I mentioned, we're going to talk about some of what's new here. What you will learn in this session, well, you've already learned what you can do in your application with QuickTime, so if that's the only reason you came, thank you very much. There are other sessions next door and down the hall. Also, we're going to talk about media facilities for the modern OS. I have no idea what that means, but it's just a way to get you to stay instead of leaving.
Also we're going to talk about what has changed in the OS and how QuickTime is changing with it. We're going to cover some answers to common questions during this session. Here, right here, from this stage you will learn how to open a movie giving a path to a file in the form of a CFString.
What if I have a CFURL that points to some media? How do I open a movie that I can play from that? Well, what if I'm trying to draw to a CG context and I have a QuickTime movie? How do I do that? Am I building up the tension for you appropriately? and other questions we're going to cover as well. If we don't answer your specific question in this session, fire me and come to the QuickTime lab. It's in Sacramento, which is downstairs near the cafe. It's not up Highway 80.
Okay, also in this session, we're going to cover the use of QuickTime with a number of different frameworks, technological frameworks that you may be using to develop your applications. We'll cover QuickTime in Carbon, of course. QuickTime is, in fact, a Carbon API itself, so that's an easy one. We're going to cover QuickTime with Cocoa, QuickTime for Java, and also, by the way, many of the APIs, if not all of them, I can't specify, are available for Win32 as well. So if you're building applications using Win32 APIs, we have solutions for you for media.
Okay. So you've seen already at the show a number of prime examples of what QuickTime can do in applications and you probably use some of these in your own work. We have some obvious ones on this list. iMovie, Final Cut Pro, Final Cut Express create video. So you would fully expect that some use of QuickTime is going on under the covers and I can confirm without a doubt that it is rumored that there is some use of QuickTime in those applications.
But QuickTime is also used in other applications that you might not immediately connect it with. And I have a list of some of them here and in fact I'll show you one or two right now. If I could have demo one up. I like this better. This is not the long walk that we have downstairs. Okay, I'll decide later.
So I have iPhoto here. iPhoto is an application that works with still images. Of course, it works with your digital camera seamlessly so that you can import images from your camera. You can edit them. You can make different things out of iPhoto. Photo albums, slideshows. QuickTime is actually used quite extensively in this application for importing images, for reading image formats, for creating thumbnails.
But there's some other interesting things going on here as well. iPhoto is capable of creating digital media in the form of QuickTime movies. There's an export item here from the file menu that you might not have seen. It has a QuickTime choice up here in this panel that allows you to create slideshows. I've created a couple of them for you.
have a confession to make, and that is, in about 20 minutes, my son is playing in a Little League game. So since I can't be there, I thought that I'd take a little look here. So these, of course, are images that were imported off of a camera, and iPhoto has made a nice slideshow of them for me, and it's added some nice effects here that QuickTime is currently rendering.
It's exported those images along with a description of the effects out to a form that QuickTime can read, and this can now all be delivered in the form of a QuickTime movie. Well, I don't really like the speed at which iPhoto has set the dissolves. It's using a uniform time for all the dissolves.
So what I actually did was I went and I exported two more slideshows from iPhoto, and I have some of the slides here.
[Transcript missing]
I've just pasted that part of the other slide show in here. So here's an example just using copy and paste editing how QuickTime can combine media together.
All of the facilities for importing and playing this media are available to your applications as well. One other app that I wanted to show you that you might assume uses QuickTime media is Keynote. And of course it does. You can drag and drop media onto slides in Keynote and Keynote will be able to play that media on slides.
But what you might not be aware of is Keynote can also create movies. You can export your presentations to QuickTime movies. Let me show you what that might look like. In Keynote's export menu, it drops down a nice sheet, gives you some choices. One of them is QuickTime.
From Keynote you can create interactive slideshows which have the same ability to be controlled by the mouse and the keyboard as Keynote has itself. You can also create self-playing movies with timed builds and timed transitions. I went ahead and I created a movie that has all of the slides for this session right here. Let me close up some windows.
Now I made this a very small one so I could email it to you after our presentation is over so you can review this at your leisure. What I'm doing here is I'm controlling this movie in exactly the same way that I control the slides in Keynote. I'm using the right arrow key to step through. I think what I'll do is email this to my mom afterwards so she knows what I've been up to for the last two weeks.
Okay, so the point of these demos is that you can do this in your applications as well, and we're going to talk about how you can do that in this session. Can we go back to slides, please? I know it's confusing because we were showing the slides, but I want to go to these slides.
Okay, first some abstractions, some things that have not changed in the last 12 or 13 years since QuickTime was originally just a gleam in Jim Batson's eye. Some of the fundamental abstractions that you will want to be aware of if you use QuickTime APIs we're going to go over right now. First of all, what is a QuickTime movie? Well, it's just an organizing principle.
It's just a catalog that tells what media should be played, in what order it should be played, and what its spatial relationships are. Formerly, a catalog of playable and editable content that describes the sources and types of content to be played together with its spatial and temporal organization.
took me a while to come up with that. Inside of a movie, there can be one or more tracks. A track is just a sequence of media. It has a shared set of properties, spatial and temporal, and typically also has the same characteristics. So a track would typically be all audio or all video or perhaps all MPEG.
A track plays media. Notice that we've gone three levels of abstraction down and we haven't talked about actual content yet. A movie is just a catalog. A track is just a sequence. Well, finally we've gotten to the level where we're actually talking about what bits get played. The media is just a container of playable stuff, an MPEG-4 file, a WAV file, a QuickTime movie file is also an example.
and in this particular graphic, what you see is a single track which plays one media file for one section and follows that up with a second media file. How does a track, how does media find the media that it plays? By means of data references. Data references are actually the main abstraction that we're going to talk about for the next several minutes in this session. It's just a way for us, QuickTime, to find the media that needs to be played.
Some specifics, it's a handle-based data structure. This is important for you to know. The handle, from the parlance of the classic Macintosh memory manager, now the Carbon memory manager, you will call disposeHandle to dispose of a data reference that you create. And you'll use other handle-based APIs for manipulating it. How big is it? Call getHandleSize and so forth.
It's semi-opaque because some types of data reference we don't publish. Some of them we publish the format of and some we do. For example, one popular form of data reference is a CarbonAliasManagerAlias. So you can actually take a look and see what's in there and use the AliasManager APIs together with those. But some of them are also opaque. Now using these simple abstractions, your application can support all of the media formats that QuickTime supports. All the video, all the audio, all the still image, all of the interactive formats. I grabbed this page off of the web.
And the folks across the hall did a nice job of integrating it with my presentation. The QuickTime product spec actually lists about 200 different formats now that we can support. In the last year, without you having to do any work in your applications, if you are already using the QuickTime APIs we're going to talk about today, you have gained support for the following formats in your app.
MPEG-4, along with MPEG-4 AAC audio. JPEG-2000, a still image format. We deliver support on that on Mac OS X. Then 3GPP, you saw how many Ps did I say? Anyway, you saw a demo this morning of QuickTime together with cell phones and the open standard 3GPP for delivering video and audio to phones. And together with that, the audio, one of the audio formats that's in the 3G spec AMR. And finally, the most important one that we're announcing for the first time in this session, Wave Format 49.
Thank you. Some fans there of GSM Audio. Okay, so the abstractions that we just went over, those have remained the same for the last 12 years. If you put those into your toolbox, they will remain the same for the indefinite future as well. But some things have changed.
Now, we didn't immediately realize this as we delivered QuickTime for Mac OS X, but some things around QuickTime changed in the transition from the classic Mac OS to Mac OS X. Some things underneath QuickTime, such as the file system and the graphics subsystem, and, well, the way we do audio, and, oh, I don't know, the way events are handled, and the way we do concurrency and threading, and, oh, the way text is rendered on the platform. Well, a few things have changed since 1990. And what we want to say is we are trying to keep up.
So in our spare moments when we're not delivering support for new multimedia formats, such as the list that I gave you just then and others that I can't talk about, or playing with new Pixlet codecs or such things, we are revving our APIs to make QuickTime a better platform citizen on all of the platforms that we deliver QuickTime for. So let's go through some of these topics. Files will be my first one. And we'll talk about new APIs that you can use.
We're getting away from some of the legacy data structures, some of the legacy idioms for the way things are talked about on Macintosh, and adopting the new ones. Now QuickTime, though you may not believe it, did not invent the FS spec. There is a rumor that FSSpec first appears in the Oxford English Dictionary. There's a reference to it in the obscure Canterbury tale, The Hacker's Tale.
In fact, the truth is that was a misappropriation. The real FS spec was first delivered on system 7 concurrently with QuickTime. And QuickTime, of course, adopted that data structure for specifying files. And our APIs are literally littered with FS specs as parameters to various calls. Now, that's not so convenient when FS specs are no longer the preferred way to refer to files.
So what do we have? We have in QuickTime an abstraction that we mentioned earlier, the data reference that allows you to refer to files, to URLs, to other locations that media might be stored in an abstract way. And so with data references, you can read data from media and play it.
You can write media back to locations out in the world. What we have with QuickTime 6.4 on Panther are the data... ...references that allow you to create new APIs for creating data references that you can use with QuickTime. Here's an example of one of them. Suppose you have a path to a file. Maybe the name contains Unicode characters.
You want to open that file and play it as a movie. What you do is the following. Use this new API, QT new data reference from full path, CFString, and it will create a data reference for you. Let me show you an example of what this might do in a moment. We not only can create these data references from full paths, there are also APIs if you have partial paths together with anchors, if you have URLs, hey, even if you have an FS spec. We also support FS refs from the Carbon File Manager.
Before I show you any of the code snippets, however, that you can just drop in your application, I want to say two words about Enter Movies. Call it. This is how you distinguish the afternoon session, in which we're talking about real APIs, from the morning session, which is driven by not showing the APIs, but showing the technology. We're going to tell you, remind you, that even on Mac OS X, it's still necessary to call Enter Movies before you call any of the movie toolbox routines. Here's just a caution.
If you're calling it from Cocoa, and yes, we support calling these APIs from Cocoa, if you have a class method that goes on to call some movie toolbox functions, some QuickTime APIs, anything in the QuickTime framework, it's probably a good idea to position a call to Enter Movies somewhere that's sure to be invoked before any of your class methods are invoked. So this is just an example of how you might do that, calling it from the initialized class method. Okay, so here's an example of using that DataRef utility to determine if QuickTime can open a file.
You want to call the QuickTime API "Can QuickTime open DataRef?" That will tell you, "Can QuickTime open the file?" It can also tell you, "Do we prefer to open it as a still image?" Or, "Can it be an image?" Or, "Does it prefer to be a movie?" What you want to do is take the form of reference that you have, a path, a URL, what have you, call the appropriate data reference utility to create a data reference, and then use that in CanQuickTimeOpenDataRef.
And as I mentioned, the DataRef is a handle-based data structure, so before you go on to doing other things, please dispose of the handle if you're not going to use that DataRef any longer. It's not a reference-counted item that's going to be disposed of for you at some time.
and Kevin Calhoun. So, let's talk about the data reference utility. Suppose you want to open a movie from a file. Same data reference utility, Qt new data reference from full path CFString. Of course, if you have a different form of reference, use a different data ref utility. The call that you use is new movie from data ref.
This one call will work with the entire range of formats that QuickTime supports. You can open WAV files locally from the Internet. You can open AIFF files. You can open 3GP files. You can open .AMR files. You can even offer WAV files that are encoded with Wave Format 49 with this one API.
Now, it's very important, before I move on, to mention, just to caution you, it's very convenient in your applications in your plists to list all of the file extensions and all of the Mac OS file types that you know how to open. Well, that's great, and it'll be fast for you to check whether a particular file, if it's dragged onto your document, whether you can accept that drop by checking whether its file extension or its Mac OS file type is in that list of things that you support.
However, you have to remember that if you support dropping QuickTime media on your applications, QuickTime is always expanding the set of media that it supports. So you do want to call CanQuickTimeOpenDataRef to determine whether you can accept a drop of media. For example, Keynote does that. and when QuickTime 6.3 shipped, it was immediately able to support .3GP and .AMR files without having to be revised. Okay, open a movie from a URL, same basic sequence, different data ref utility.
Qt New Data Reference from CFURL. Suppose I want to write a movie to a file. I want to create a new file or I want to overwrite an existing file. In this particular example, I'm calling the same DataRef utility Qt New Data Reference from FullPath CFString, but this time I'm referring to a file that may or may not exist. That will work just as well as the earlier uses where we're opening an existing file.
In this particular case, in this code snippet, there's a slight wrinkle. I create the DataRef. Then I say I want to create storage for a movie at the location that the DataRef points to by means of createMovieStorage. If you take a look at the parameters there, you'll see that we're saying go ahead and overwrite anything that was already at that location. We're also supplying an HFS creator code to identify it as being associated with our application. What that call returns, createMovieStorage, is an instance of a data handler.
You can think of it as an object that will just do the writing for you. It is, in fact, an instance of a component, a QuickTime component that knows how to read and write data from data references of the type that was returned in this case by Qt New Data Reference from FullPath CFString.
So that thing will know how to write the movie to that storage, and it will do that when I call add movie to storage. I tell the data handler, please do that work for me. And once I'm done, I say close movie storage. That will close down an open connection or close an open reference to a file.
And it will also close the instance of the data handler. And since I'm done with the data ref, I dispose of it. This snippet of code will be capable of writing movies to any type of storage that QuickTime has a data handler. So this will work with files and other forms of storage as well.
And of course, more immediately, it will work whether your path names have Unicode characters or any other sort of characters. I should have mentioned earlier that in the call QT new data reference from full path CFString, that is a mouthful. You tell us the type of path that is. We typically give that type of path as the native or default type of path, but we support a range of path types as well.
Okay, you can do a similar thing in Cocoa without telling QuickTime to write to the file via add movie storage or something like that. You can get from QuickTime a serialized form of the movie in memory by means of put movie into handle. That will give you the thing that you want to write someplace. And then in this particular snippet I'm using NSData. I'm actually copying that serialized form to an instance of NSData, then using NSData to write out the file. So this will work perfectly well also.
For extra credit, if you can rewrite this code snippet not to copy the serialized movie in memory, I will say a hearty congratulations. It is possible, but it goes beyond the scope of what we're going to talk about today. All right, so what did I write in those snippets? I wrote movies to files.
And as we said earlier, a movie is just a catalog. It's just organizing data. It doesn't necessarily include the media also. Well, what if I want to write the movie, the organizing catalog, together with the media? In QuickTime parlance, that's called flattening the movie to a location. And the API for doing that is flatten movie data to data ref. Get a data ref, flatten the movie to it, and you're off. You now have a file, in this particular case, with all of the media data and the movie stored in the same place.
Okay. So here's something that I know that we haven't shown on a WWDC stage before. And as soon as I show you this, I'm going to show you how you can get into serious trouble using this. If you want to know what media a movie plays, it's possible to do that.
All you need to do is to iterate through the data references that a movie uses. And here's how to do it. You use the abstractions that we talked about earlier. In this particular case, I'm looking at the first track of the movie. But of course, I can iterate through all the tracks in a more involved example. That wouldn't fit on a slide. And I get the media for that track.
[Transcript missing]
Once I have the data handler, I have another set of data reference utilities that I haven't mentioned yet that allow you to get information back from a data handler about a data ref. In this case, I just want the full path back. I want to know where these files are and I want to be able to manipulate them with other APIs in NSFileManager, for example, or in the CarbonFileManager. And here's how we do it. Make sure you clean up, close down your data handlers, dispose your handles, and everybody else. And here's how we do it. Make sure you clean up, close down your data handlers, dispose your handles, and everybody else.
for a graphical interlude. We got these cool graphics last week. and the advice to mark all of our code snippets either with this best practices icon or with a different icon. Now I didn't have time to do all that, so I wanted to tell you that if you're used to seeing these icons during the show and you're reluctant to use any code snippets that are not marked in that way, all of the code snippets in this presentation, unless otherwise noted, are best practices. They've been certified by a board of QuickTime API engineers who are sitting, I think, right over there. Now after saying that, I will immediately show you something that is not a best practice.
In this particular case, I'm going to use the power that I've just given out to the whole world to iterate through all the data references in a movie, and I'm going to load all the media data into memory in one small loop. Now, this is a very interesting thing to do, and it might be fun if you want to swamp the VM, but it's something to avoid.
If QuickTime is capable of playing large amounts of media data without loading it all into memory, it's probably possible for you to examine it or copy it or do whatever you need to do without loading it all into memory, too. You should be aware that these data refs can point to very large amounts of media data, gigabytes worth of DV or audio or high-res video of some kind, and it's probably not a good idea to write code that loads arbitrary media into memory like this.
Okay, so I can open movies, I can write movies back to files. Suppose I wanna write a movie to a different kind of file. I wanna export data from a movie to a different file format. Here's a code snippet using the DataRef utilities that takes the audio from a movie and exports it to a WAV file.
[Transcript missing]
So we've talked about movies. The same procedures work for opening images. How can you draw in any image in any format that QuickTime supports? Get a data reference, then get a graphics importer for that data ref using the interestingly named API, getGraphicsImporterForDataRef with flags.
A graphics importer is an object, again it's an instance of a QuickTime component, but you can think of it as an object that has methods that do things with images, like draw them, or transform them, or export them to other formats. For example, if I wanted to export an image to a file, all I need to do is open an instance of a graphics exporter. In this particular snippet, I happen to be using the ping exporter because ping is an excellent graphic image file format.
Once I've got that open, I want to tell that instance of the graphic exporter what the source of the image is. I'm saying, please make the source of the image to export this graphics importer I just opened a moment ago using the method that I showed you, getting a graphics importer for a data ref.
Then I want to tell the graphics exporter where to write the image file by means of, again, a data reference. Then I tell it to do the export. And with that few lines of code, you can write any of the image file formats that QuickTime can write. And of course, clean things up, close components, dispose handles.
So that covers the basic level of data reference utilities. We hope this will get you past some of the blockers, some of the conceptual blockers that developers have run into looking at the QuickTime APIs for the first time on Mac OS X and saying some of these things are not like the other.
We're trying to be more like the other and make it easier for you. All right, so let's move on to graphics subsystems. Things have changed in graphics. When QuickTime, in its nascent years, it's the native graphics subsystem was, of course, QuickDraw on the classic Mac. Since then, other graphics systems have become available also.
Now I want to say, like I said for files, that we have an abstraction that will shield you from all the details of all these graphic subsystems. And if you use our abstraction, then you don't have to worry about the details of the underlying graphic subsystem. And if I said that, it wouldn't quite be true, but we have something of that flavor. We still use some of the basic quick draw data structures and APIs, but you can use them in combination with the graphics subsystem that you are using in your application. And I'll talk about how to do that.
If you want to play a movie in a window, what you need to do is to get from the window its QuickDraw port. And that's a very simple thing to do in Carbon or Cocoa. If you have the Carbon window ref, you get the QuickDraw port that's associated with that window by means of getWindowPort. Then you can tell QuickTime to draw a movie there by means of the API setMovieGWorld.
In Cocoa, you can get the Carbon window ref from NSWindow from a public method called windowRef. So this is all very straightforward. But you say, I wish to play movies into off-screen buffers. How do I do that? Well, if you have the buffer set up and all you know is the pointer, the location in memory where the pixels are going to be drawn, you know the bytes per row of your buffer, you know the size of your buffer, the width and height.
And one more thing, you need to know the QuickDraw pixel format or you need to map from the pixel format that you're using, whether it's a CoreGraphs and Quartz pixel format or an OpenGL one. You need to do a little mapping to the QuickTime or QuickDraw way to describe that pixel format. Then you can create a data structure that allows us to draw the movie there. You call newGWorld from pointer with that information and that will allocate a GWorld that allows QuickTime to access those bits. Yes.
Your buffer, which you may be doing other things too also. You might be composing movies with other things and so forth. This is exactly what Keynote does, by the way, to be able to render movies to OpenGL textures. It creates a GWorld that QuickTime can use to render to that same area of memory.
Okay, same thing for images. In this case, you create the GWorld and then use Graphics Import Set GWorld to do the same thing. Then Graphics Import Draw to draw there.
[Transcript missing]
The key API call here is QDPickedDrawToCGContext. This is a public API that you can use. This method will work for you.
All of these code snippets, by the way, are available in a document that we're making available via your ADC connection. So you don't have to jot all this down. In fact, the samples in that document are a little bit more, are a little bit fuller than what I'm able to show on stage. Again, I'm cleaning up after things.
How old is the API kill picture? Does anyone know? How many WWCs have you been to? enough to know? Well, that's more than enough. Okay. So CG images, you don't have to get a quick draw picture to do all operations in QuickTime. We now support the ability to read still images and give you a CG image and we support the ability to take a CG image and write out to an image file.
A new graphics importer call, graphics import create CG image, will give you a CG image from any format that QuickTime can read by a graphics importers by this method. And similarly, you can write out two image files from a CG image using graphic exporters. We saw the example before of how to use a graphics exporter. The only difference here is I'm using the API graphics export set input CG image to tell the exporter to take the image from the CG image and then write that out.
How many dispose handles have I shown during this session? It's probably more than you've seen anywhere else at this conference so far. Okay, so let's take a break for a few minutes from code snippets. Something else that has become more widespread on the OS is color matching. Tim Schaaf mentioned it this morning.
So I won't repeat all of this except to underscore the point that by default, graphics importers will match when they draw if there is a color profile stored in the image. This happens by default. You don't have to do any work. So when Tim Schaaf showed his demo of BBEdit suddenly able to do color matching, did that require any changes to BBEdit? Well, no. It's just using graphics importers and now it just works.
However, something that Tim didn't mention is that if you use some of the code snippets I showed you to translate from one graphics image format to another, you should be aware that we now, as much as the image format allows us, move the color profile over from the source to the definition--to the destination and this just happens. It just works.
More details about how to do this, particularly if you're already doing color matching of your own when using graphics importers, come to session 716, Advanced QuickTime Programming Techniques and there they will speak even more advanced language than I'm capable of Another subsystem that's changed underneath QuickTime we are changing to keep up is audio. We have on Mac OS X core audio. You heard this morning that we have a complete reimplementation of QuickTime sound media on top of core audio. You have the opportunity to try that out on your Panther C disk once you install that.
One of the things that wasn't mentioned this morning, just as you can use QuickTime in combination with Quartz in the ways that I told you earlier, you can use QuickTime in combination with Core Audio. Come to session 7.11 to find out how to extract audio from a movie in a form that you can manipulate using Core Audio. So these technologies work together better than they ever have before. All right, another area that's changed underneath and around QuickTime. We have a new text rendering engine on Mac OS X. It's the Apple type system for Unicode imaging, and it stands for something.
and in any case, it is the native rendering engine for Unicode on Mac OS X. And it does a great job of rendering Unicode. What QuickTime has done on the Mac before, you could always store Unicode text in your movies since QuickTime 3. On Mac, however, we were transcoding the Unicode to a different encoding before rendering it.
And so you lost some faithfulness to--some fidelity to the text. That's no longer the case. We have complete fidelity to Unicode text when rendering. Now, there's a cost and I want to be clear on this. You're going to lose the ability to render text with QuickDraw Shadow or QuickDraw Outline.
Yeah. How many people here have looked at what QuickDraw does to add a shadow to a bitmap font? How long has it been? Take a look again. If you're worried about the loss of this, take one look and you won't worry anymore. Let me give you a quick demo. is going to be talking about the new features of QuickTime 6. Hello, everyone. I'm Kevin Calhoun, and I'm going to be talking about the new features of QuickTime 6.
A description in XML format of what a text track might look like. Here, starting with QuickTime 6.3, we have the ability to specify Unicode text. We're using UTF-8 encoding in this example because it is stored as XML. And we have the ability--let me highlight this for you. It's hard to see in the back, I know, but you can set an attribute that says, "Write the text vertically." What does it look like? Well, let me import it with QuickTime right now. The very same XML document.
And this is what it looks like. The first frame renders the text horizontally and you see that if I scale it down, scale it up, we have a very smooth text now. And the second frame writes the same text vertically. So that's all available for you. Once you have this text into a text track, of course you can move it around with QuickTime media just as easily as any other. Let's move back to slides.
All right, so we talked about some subsystems that have changed. Things that have changed around and above QuickTime include the user interface. Now, this has changed somewhat since 1990. For example, we don't have modal dialogs anymore. We have panels. But not only has the terminology changed, also the way that users interact with these things have changed and their appearance has changed quite a bit as well. QuickTime has some UI of its own that you can display in your applications for configuring operations such as recompression, export, import.
If you choose to display this UI, you get well-standard UI that may or may not match the other UI in your application. That's a problem that we're going to be working on over time. We're going to tell you how we're going to do that. But the good news is, and I'll show you some code snippets in a moment, you can now display certain QuickTime modal dialogs as sheets. All right, so we talked about some subsystems that have changed around and above QuickTime. For example, we have panels.
But not only has the terminology changed around and above QuickTime, we're going to tell you how we're going to do that. But the good news is, and I'll show you some code snippets in a moment, you can now display certain QuickTime modal dialogs as sheets. is the founder of the component properties.
First some code snippets. If you want to display QuickTime standard compression dialogues as sheets, we have a new scSetInfo, the standard compression set info API selector that tells you to display a dialogue as a sheet instead. You tell it what the parent window is. If you have the Carbon window ref, it'll just work.
And when you say scRequestImageSettings the standard compression sheet will now come down from the window title bar as you would expect on Mac OS X. It's also possible to do that with a video compression dialog. And it's also possible to do, as I mentioned, with the effects parameter dialog as well. What we do in this case is we call Qt Create Standard Parameter Dialog, setting the option PDOptionsDisplayAsSheet.
And then we tell it to do something clever. This API was originally designed to work with the classic Macintosh Dialog Manager, mode-less dialog support. Now we just tell the parameter dialog to run itself in its own event loop. And that's what it does. It brings down the sheet in this case, handles the user interaction, and then when the user dismisses it, it goes away and you have the settings that the user selected.
Okay, I'm running behind, so instead of showing you sheets coming down from title bars, I'm just going to stay with the slides. Sorry about that. Meantime, someone can translate the text that we put into that movie. Okay, component properties. This is an important direction for us. If you are a developer of a movie exporter or of a codec or of anything that is used in combination with a QuickTime process, we would like to work with you over the next year to standardize sets of properties that are common for your component type.
You can imagine that exporters will have a common set of properties and we would like to roll out in a way that's similar to the way over time Apple worked with developers to add support for Apple events in their applications with standard Apple event suites. We want to work with component developers to add support for standard property settings. This will allow us to factor the configuration of QuickTime operations from UI.
So you'll hear a lot more about that from us over the lifetime of Panther and QuickTime 6. You'll see these APIs in the QuickTime framework in your Panther seed. These APIs are actually part of the component manager, although they're not in that framework that the component manager is part of on your seed disk. Okay, so you'll hear more about that in the upcoming months.
All right, something else has changed. It is now possible to do operations on concurrent threads, and there are many different threading models that are available on Mac OS X. However, there's been some difficulty to date of making QuickTime processes operate on secondary threads. We really wanted to operate on the main thread.
Now we have the ability, as was mentioned this morning, for a certain set of operations to configure them and to carry them out on secondary threads that do not block the UI. This is a major win if you have an application, for example, that exports a lot of data.
You saw my code snippet earlier for exporting audio to a WAV file. What if that's a lot of data? Does the user just have to wait around while a progress dialog tells me how much has happened? Well, we have the ability now for certain processes and certain operations to happen on alternate threads.
More details in the advanced QuickTime programming technique session. Please come to that to find out how to do that. Especially come to that if you are already calling QuickTime APIs not on the main thread, because you may have interesting side effects that you're not aware of. There are certain restrictions that you want to be aware of.
Now you'll note that even though that this is a fairly introductory session to QuickTime APIs and to QuickTime new APIs, I have departed from many years of tradition. I have not shown you how to take a movie that I've opened and then create a movie controller for that movie, and how to put the movie controller in a window, and how to route user events to the movie controller. That, I think, has been shown at every single QuickTime API session since 1935.
But today we are breaking with tradition because we have finally arrived at a point at which we have intermediate level modules that will do that work for you. You don't have to worry about it any longer. So if you use these APIs I've shown you to get a movie from a file or some other place in the world, all you need to do is tell that movie, well, you movie, you play in this NSMovieView. Or you, you movie, you play in this CarbonMovieControl.
There are also third-party ActiveX controls available if you're using Win32 APIs. And those things are able to take care of all those programming details for you. Like, well, how do I get an event in the form of a classic event record to tell the movie that a click happened? Don't even worry about it.
However, if you choose to worry about it, there are some details that you might want to be aware of. For example, the age-old question, "How do I tell QuickTime Well, here's some time for you to do processing. QuickTime movies, since they're normally heavily display oriented if you're playing them where the user can see them, they do run on the main thread. And QuickTime is architected in such a way that playback doesn't block the UI.
But the way that it works is that the application has to tell QuickTime, here's a little slice of time that you can use for doing some processing. Fetch some media that you need to decode. And decode some. And oh, by the way, return in like no time at all.
So here is what you will want to do on Mac OS X. We now have a science, whereas before it was all magic, we now have science attached to how often you need to tell QuickTime, here's a little time for processing. What I have here is a snippet of code that I'm using in combination with a CF timer.
And when my CF timer's time task fires, what I'm going to do is I'm going to tell a set of objects, in this particular case, this primary objects or underscore primary objects thing, it might be a CF set, it's a list of objects that manage QuickTime movies, I'm going to tell all of them, run your function, run your application, and then I'm going to tell them to run the function.
[Transcript missing]
or we really need you to do it again real fast. And so QuickTime will return to you an interval that you can wait before calling this again. And then what you want to do is tell your CF timer to fire after that interval has expired and then this will happen again and all your QuickTime movies will be tasked. You can set a minimum interval so that you're not spending all the CPU time doing this.
And then the function that you might fire on your objects, that setApplier function, might cause this to be fired on all of your objects. In this case, I'm using a Cocoa example. I actually am using an NSTimer with a toll-free bridge to CFTimer to fire this function that will tell all of my objects the value parameter passed in here to call a method idle. And that idle method will probably call QuickTime and say MCIdle if it's using the movie controller or moviesTask if not. So that's how to do that on Mac OS X.
Here's something really obscure. But I promised that I was going to answer this question at the beginning of the session. And since I am forced to keep my promise or they'll throw me off the stage, what if I have an NSTime interval and I want to tell QuickTime that's that amount of time? What do I do? An NSTime interval is a floating point value.
It's a double precision value that expresses a number of seconds as a floating point value. What I want to do is turn this into a data structure that QuickTime can recognize as that same amount of time. Well, what we're doing here is using some--an obscure function in the math package. Please give me the magnitude of that NSTime interval.
And according to the magnitude, that's the frex--. is the founder of the NSTimeInterval function. According to the magnitude of that NSTimeInterval, we're going to choose a time scale to use to represent the time value in QuickTime. So if the value is really large, we're going to use a smaller time scale.
If the value is relatively small, we'll use microseconds because that's a very good timescale to use with QuickTime. Then once we've chosen the timescale, we're going to go ahead and convert that NSTimeValue to a time value. We multiply the value by the timescale and write it into the time record. So if you're trying to call an API like setMovieTime, where the time interval has been expressed to you as an NSTime interval, you can use a function like this to do the conversion.
You're thinking, why did I show that? OK. So I mentioned to you earlier, to take care of a lot of these details, you can use higher level objects that know how to do things like process user events. They know how to task movies. In some cases, they have higher level methods so that you don't even have to use any of the file manipulation that I showed you earlier.
For Carbon, we have the movie control. For Cocoa, we have nsmovieview. And for Java, we have two components, a Java AWT component and a Java Swing J component that you can use. And I mentioned there are third party ActiveX controls as well. If you're a Carbon app, you can use a Carbon movie control via the simple API, create movie control, and it will do all the work for you.
We're revising the Carbon movie control to fix the major gotcha with it, so that there were some limitations in its use if you combined it with the use of HI views in a Carbon app, some problems with setting the clip. We're going to take care of that for you in QuickTime 6.4. Let me show you just how easy that can be.
So back to Xcode, recent project, demo movie control. Here I have a very simple application that, well, plays arbitrary QuickTime movies. Basically, since you probably can't see the whole flow of code in the back of the room, it does call and their movies. It's a good citizen. It prepares QuickTime for calls upon movie toolbox functions.
It then calls a function that implements itself, "Give me a movie," that uses some of the very same APIs that I showed you earlier. What this function does is uses a panel to allow the user to select a file and extracts from the API that displays the panel a reference to the file. Then it creates a data ref for that file and opens the movie via a new movie from data ref. Then what it does is creates a Carbon movie control where I create movie control. And it does a little housekeeping with the control.
And that's basically it. That's all it takes for your application using Carbon to be able to display arbitrary QuickTime media. So I should be able to open up any of these movies that I created earlier. I have a little bug here. I've got to resize this before it shows up. and here it is. This slide show that iPhoto created can be displayed in this Carbon app with just that amount of code.
something similar in Cocoa. In this particular example, I was too lazy even to alter the example. This simple Cocoa movie is available for you as sample code on Apple's website. It uses NSMovie and NSMovieView in order to implement a very simple application that does something very similar. In this particular case, instead of displaying a panel to allow the user to choose arbitrary media, it reads the media from the application bundle itself using NSBundle.
Well, how does it do that? It gets the URL for the media from NSBundle, creates a data ref for the URL, and then uses new movie from data ref. And then it opens up the movie and displays it in an NSMovieView. Thank you for the audio. Should have turned it down. Okay, so that's all that you need to do. Back to slides.
If you are using Java, the good news is our support for QuickTime for Java is ongoing. We have a new version of QuickTime for Java, Java 6.1 is its version number, that's available for seeding, I believe, today. You can get access to it from your ADC account. It works with both JDK 1.3 and 1.4.1 on Windows with the Sun Java VM and on Mac OS X.
It has a complete up-to-date set of bindings to QuickTime C APIs. So all the APIs that we've gone over today and the other APIs in QuickTime's API set, you can call using QuickTime for Java. But it also has higher level modules in the QuickTime.app.view package for displaying movies, both using an AWT component and a swing component that you can use. Now, if you're using earlier versions of QuickTime for Java, some code migration might be necessary. We'll talk about the details in a moment. But let's look inside the package to see what you get.
We have a number of classes that will do some work for you. If you have some media and some references to the media, you can use a QuickTime factory class to create the components to display the media. We have some holdovers from the earlier version of QuickTime for Java, Qt Image Producer, Movie Player, Graphics Importer Draw we continue to support. The Java AWT component and the QuickTime Swing component, I believe I have misnamed on this slide. This name doesn't match what's in the Seed, but don't worry, we'll reconcile that shortly.
And here's an example of how you can use this. If you're using Java AWT to display things, this is basically all you have to do. If you have a path, you say new Qt file, and then you say you want a movie from that file, create a movie controller for that movie, and then you want Qt Factory to create a Java AWT component that is capable of displaying that movie and knows how to allow the user to interact with it.
That's all you need to do. If you're using Swing, similar code. In this case, you're saying that you want a movie player from the movie, and then you want from Qt Factory the Swing component that's capable of displaying an instance of the Swing component that's capable of displaying the movie.
and that's all there is to that and you can display all the QuickTime media that you've seen here at this session in your Java applications. Now, I mentioned earlier that some code migration might be necessary if you're using earlier versions of QuickTime for Java. We have deprecated a number of packages. Some of these are smaller packages and some of them were larger.
But why have we done this? There are two reasons. One, some of these packages depended on behavior that was available on legacy versions of OSs that QuickTime was housed on and that were supported in legacy implementations of Java SDK on Mac. For example, some of these were tightly coupled with QuickDraw support.
So what we've done is said, well, instead of supporting all of that legacy stuff, what we want to do is to move towards a model which is more consistent with the standards that have emerged in Java over time. A number of the classes in these packages were designed before standards emerged in Java, such as Java Swing. So we gave you solutions for doing things in these packages that were completely orthogonal to the way Java application developers typically work today. So what we're doing now is we're changing our support at that intermediate level to adopt the standards that have emerged.
Now some of these packages may have things in them that you are dependent on. Some code migration will be necessary on your part. Be part of the seed, find out the details, and then work with us. We'll help you make the move and we'll talk about options. I have a demo over on my Windows machine.
[Transcript missing]
Here is an example of the use of the Java AWT component that we supply for you in QuickTime for Java. It has the ability, of course, to play the movie. with high quality audio straight out of my bio and the ability to select an alternate piece of media from using standard Java UI and display that as well. Quick example of
[Transcript missing]
We're using here several instances of our swing component together with some other things. This is Java animation down here.
And here is an image using the image drawer. And here is a movie. Now I show you this on Windows to illustrate the point that this is going to work with exactly the same implementation on both Mac OS X and on Windows using the same Java code. It delivers on the promise of the cross-platform compatibility of Java apps. Okay.
Back to slides. Ooh, quicker than I am. I haven't talked too much about QuickTime for Cocoa as yet. I thought at one point while we were developing the session that I would have a fantastic announcement to make for you at the end of the session that would keep you on the edge of your seats for the entire time.
However, Tim Schaaf went and blew it this morning and told you that we're doing initial work on QuickTime for Cocoa and we'll have a seed later this summer that goes beyond what's already available for support for QuickTime in the app kit. Well, let's talk about what that support is that you already have in the app kit. You have NSMovieView and NSMovie.
They provide fundamental support that has matured and is extremely reliable. You can, with these classes, manage and play all of the media formats that QuickTime supports. Very simple to use. You don't even have to go down to the C-level API to open a movie from an arbitrary file or URL. Example of usage is up there on the wall.
A number of Apple applications use this facility. Sherlock uses this, for example, to display movie trailers in its movies channel. What are we going to do? Suppose you put a bunch of QuickTime programmers together in a room and you gave them the problem of designing and implementing a set of Cocoa classes that integrated well with Foundation and AppKit that used the same data structures and methodologies that were common in Cocoa applications. And yet, had the flavor of QuickTime, what would we do? Well, naturally, what we would do is to use the very same abstractions that we talked about at the beginning of the session.
The same ways that we talk about media in QuickTime for the last 12 years, we're going to talk about it in Cocoa as well. Here's a sampling of the kinds of classes that you can expect from us when we see QuickTime for Cocoa later this summer. You'll be able to manipulate movies.
A lot of the very same code that I've put in my slides will be in the implementation of Qt Movie. So now, after you've sat through all of this, you can realize if you're a Cocoa developer, I didn't need to know that at all. Because we'll take care of all of that for you in these classes.
So now it will be possible with even fewer lines of code for you to load all the media that a movie plays into memory. Finally, we have some classes that help us to bridge to other APIs in common use. I listed QT time here because it knows how to do that FREXP thing that I mentioned earlier.
You can initialize a time, a QT time from an NS time interval, from a time record, from a time value, from a time value of 64, from a comp time value, are there any more? And it will know how to deal with it and then you can pass that around to express time in QuickTime for Cocoa.
So look for that later this summer. If you are interested in this session, please do not hesitate to contact us. We are happy to answer any questions you have. Thank you. I hope you enjoyed this session. I hope you enjoyed it. We will see you next time. Bye-bye.
Okay, so I covered a lot of material in this session. There's a lot more to be said about new QuickTime APIs and new capabilities here at the conference. Now, I want to tell you, even if you use these intermediate level modules like NSMovieView or the Carbon Movie Control, in all of these environments, including Java, you have access to the QuickTime primitives, the movie, the track, the media, and you can use the QuickTime C APIs if you need to, to extend the functionality of the classes, the modules that you're using. Also, as requirements are presented to the QuickTime team. We expand and update our API sets to cover new needs. This is happening all the time. QuickTime is a living work.
This year alone, we're talking about threading, we're talking about new audio facilities, we're talking about improved color matching. You can expect this kind of expansion and an increase in functionality from QuickTime every year. You can gain access to all this functionality in your applications. Use the APIs that I've mentioned, and your application will grow with QuickTime.
Now, if you have needs that I haven't covered here, if you have some problems in your application that we haven't talked about, an excellent place for you to go to get more information is the QuickTime Lab in Sacramento downstairs by the cafe. But there are other sessions for you to go to as well where some of these topics will be covered formally. If you didn't go to the State of the Union this morning, well, buy the DVD.
The session that will cover more details about audio in QuickTime, well, how exactly did we reimplement QuickTime sound media using Core Audio? I don't know if I'll actually tell you all the details, but how can I use Core Audio in combination with QuickTime? Go to the session in Russian Hill. That's Wednesday, tomorrow, 9 a.m. Get up early. Be here.
What if I want to know these advanced QuickTime programming techniques such as, well, multi-threading? Come to the session in Pacific Heights. That's tomorrow at 2:00 PM. In fact, that's this room here, I believe. will camp out right back here. Plenty of room. All right, what if I want to follow up on something that was mentioned by Tim Schaaf this morning? What if I want to plug in modules to QuickTime Streaming Server to add functionality on the server side? Come to the QuickTime Streaming Server programming session. That's at the mission, 2 p.m. Thursday.
Finally, something that I didn't mention here, but similar to the flavor of these intermediate modules that I talked about for Cocoa and for Carbon, there is the ability to use QuickTime in other programming environments as well. Well, what if I just want to play a QuickTime movie in my Visual Basic app? Yes, I can say Visual Basic on this stage at this conference.
I think. What if I want to play a QuickTime movie in my application that I created with Apple Script Studio? What if I want to play a QuickTime movie in an application I create with Real Basic? There's a session that will cover the details of how to do that. It's called QuickTime Alternative Programming Environments. Lots of great music, lots of great programming. Pacific Heights, this room, Friday, 10:30. Is there music? No music.
Okay, so if you have questions after the conference and you want to email somebody to make sure the question is appropriately routed, your person to contact, Guillermo Ortiz, QuickTime man, can you do any better than that, at Apple.com. Also an alternative contact for the QuickTime Cocoa seat, so QT Cocoa seat at Apple.com or QuickTime man.
for yet more information. You can turn to the reference library that's available for QuickTime already on the Apple developer website. QuickTime, of course, is a mature technology. It's well documented. And here are some documents that have been made available recently for QuickTime and their paths from the ADC home. So shop for information on the web. And yet more places to look on the web for information.
and Kevin Calhoun. And finally, if you miss any of the others, do not miss the opportunity to meet with QuickTime engineers, those irascible yet charming engineers who provide QuickTime for you. In fact, provide a new version of QuickTime every several weeks for you are here at the conference and they're at the QuickTime lab and they're willing to help you use QuickTime in your application. So go there and find out just how dedicated these people really are.