Locating Tracks, Saving Movies, and Modifying Movie Properties

The Movie Toolbox provides a set of functions that help your application locate a movie’s tracks and media structures. This chapter describes these functions and how to use them. In addition, the chapter discusses functions you can use to save movies, capture and restore the edit state of a movie, and modify movie properties. A later section of the chapter discusses support for progressive downloads.

The Movie Toolbox identifies a movie’s tracks in two ways. First, every track in a movie has a unique ID value. This ID value is unique throughout the life of a movie, even after it has been saved. That is, no two tracks of a movie ever have the same ID, and no ID value is ever reused. Second, a movie’s current tracks may be identified by their index value. Index values always range from 1 to the number of tracks in the movie. Track indexes provide a convenient way to access each track of a movie.

There are several functions that allow you to find a movie’s tracks. You can use the GetMovieTrackCount function to determine the number of tracks in a movie. Use the GetMovieTrack function to obtain the track identifier for a specific track, given its ID. The GetMovieIndTrack function lets you obtain a track’s identifier, given its track index.

You can obtain a track’s ID value given its track identifier by calling the GetTrackID function.

You can determine the movie that contains a track by calling the GetTrackMovie function.

The GetTrackMedia function enables you to find a track’s media. Conversely, you can find the track that uses a media by calling the GetMediaTrack function.

Saving Movies

The Movie Toolbox provides a set of high-level functions for storing movies within files. These files have a file type of 'MooV' and a resource type of 'moov'. Your application can gain access to existing movies with either the NewMovieFromFile function or the NewMovieFromDataFork function. Once you have loaded the movie, your application uses the functions that are described in this section to save any changes you have made to the movie.

You can use the AddMovieResource function to add a new movie resource to a movie file. Your application can use this function to save a movie that it created using the functions. You can use the UpdateMovieResource function to replace an existing movie resource in a movie file. You can remove a movie resource by calling the RemoveMovieResource function.

The movie resources that your application creates with the AddMovieResource and UpdateMovieResource functions may contain references to movie data. These references identify the data that constitute the movie. However, the movie data can be stored outside of the movie file. If you want to create a movie file that contains all of its movie data, use the FlattenMovie or FlattenMovieData function. These functions can also be used to store the movie data in the movie file’s data fork, or to interleave the media data to optimize performance.

The PutMovieIntoHandle function places a QuickTime movie into a handle. You can then convert the movie into specialized data formats.

The HasMovieChanged and ClearMovieChanged functions allow your application to work with the movie changed flag that is maintained by the Movie Toolbox. You can use this flag to determine whether a movie has been changed.

The movie changed flag indicates whether you have changed the movie. Such actions as editing the movie, adding samples to a media, or changing a data reference cause the flag to indicate that the movie has changed. There are several operations that the movie changed flag does not reflect, including changing the volume, rate, or time settings for the movie. These settings change frequently when a movie is played. Your application must monitor these settings itself.

The Movie Toolbox also supplies functions for storing and retrieving movies that are stored in the data fork of a file. These functions provide robust data reference resolution and improve low memory performance. The NewMovieFromDataFork function enables you to retrieve a movie that is stored anywhere in the data fork of a file. You can use the PutMovieIntoDataFork function to store an atom version of a specified movie in the data fork of a file.

Time Base Callback Functions

If your application uses QuickTime time bases, it may define callback functions that are associated with a specific time base. Your application can then use these callback functions to perform activities that are triggered by temporal events, such as a certain time being reached or a specified rate being achieved. The time base functions of the Movie Toolbox interact with clock components to schedule the invocation of these callback functions; clock components are responsible for invoking the callback function at its scheduled time. Your application can use the functions described in this section to establish your own callback function and to schedule callback events.

You can define three types of callback events. These types are distinguished by the nature of the temporal event that triggers the Movie Toolbox to call your function. The three types are

You specify a callback event’s type when you define the callback event, using the NewCallBack function.

You specify whether your event can occur at interrupt time when you define the callback event, using the NewCallBack function. Your function is called closer to the triggering event at interrupt time, but it is subject to all the restrictions of interrupt functions (for example, your callback function cannot cause memory to be moved). If your function is not called at interrupt time, you are free of these restrictions; however, your function may be called later, because the invocation is delayed to avoid interrupt time.

The NewCallBack function allocates the memory to support a callback event. When you are done with the callback event, you dispose of it by calling the DisposeCallBack function.

You schedule a callback event by calling the CallMeWhen function. Call CancelCallBack function to unschedule a callback event.

You can retrieve the time base of a callback event by calling the GetCallBackTimeBase function. You can obtain the type of a callback event by calling the GetCallBackType function.

Creating and Disposing of Time Bases

This section discusses the Movie Toolbox functions your application can use to create and dispose of time bases.

The NewTimeBase function lets you create a new time base. You can use the DisposeTimeBase function to dispose of a time base once you are finished with it.

Time bases rely on either a clock component or another time base for their time source. You can use the SetTimeBaseMasterTimeBase function to cause one time base to be based on another time base. The GetTimeBaseMasterTimeBase allows you to determine the master time base of a given time base.

You can assign a clock component to a time base; that clock then acts as the master clock for the time base. You can use the SetTimeBaseMasterClock function to assign a clock component to a time base. The GetTimeBaseMasterClock function enables you to determine the clock component that is assigned to a time base. You can change the offset between a time base and its time source by calling the SetTimeBaseZero function.

You can set the time source of a movie by calling the SetMovieMasterTimeBase and SetMovieMasterClock functions.

Working with Movie Time

Every QuickTime movie has its own time base. A movie’s time base allows all the tracks that make up the movie to be synchronized when the movie is played. The Movie Toolbox provides a number of functions that allow your application to determine and establish the time parameters of a movie. This section discusses those functions. Later sections in this chapter discuss the Movie Toolbox functions that allow you to work with the time parameters of tracks and media structures.

You can use the GetMovieTimeBase function to retrieve the time base for a movie.

You can work with a movie’s current time by calling the GetMovieTime, SetMovieTime, and SetMovieTimeValue functions.

You can work with a movie’s time scale by calling the GetMovieTimeScale and SetMovieTimeScale functions.

The Movie Toolbox can calculate the total duration of a movie. You can use the GetMovieDuration function to retrieve a movie’s duration.

Your application can call the GetMovieRate and SetMovieRate to work with a movie’s playback rate.

Working With Movie User Data

Each movie, track, and media can contain a user data list, which your application can use in any way you want. A user data list contains all the user data for a movie, track, or media. Each user data list may contain one or more user data items.

All QuickTime user data items share several attributes. First, each user data item carries a type identifier. This type is similar to a Resource Manager resource type, and is stored in a long integer. Apple has reserved all lowercase user data type values. You are free to create user data type values using uppercase letters. Apple recommends using type values that begin with the copyright symbol to specify user data items that store text data.

The Time Structure

The Movie Toolbox provides a number of functions that allow you to work with time specifications. Many of these functions require that you place a time specification in a data structure called atime structure. The time structure allows you to fully describe a time specification. The TimeRecord data type defines the format of a time structure.

struct TimeRecord
{
    CompTimeValue       value;      /* time value (duration or absolute) */
    TimeScale           scale;      /* units per second */
    TimeBase            base;       /* reference to the time base */
};
typedef struct TimeRecord TimeRecord;

Field

Description

value

Contains the time value. The time value defines either a duration or an absolute time by specifying the corresponding number of units of time. For durations, this is the number of time units in the period. For an absolute time, this is the number of time units since the beginning of the time coordinate system. The unit for this value is defined by the scale field. The time value is expressed as a CompTimeValue data type, which is a 64-bit integer quantity. This 64-bit quantity consists of two 32-bit integers, and it is defined by the Int64 data type, which is described next in this section.

scale

Contains the time scale. This field specifies the number of units of time that pass each second. If you specify a value of 0, the time base uses its natural time scale.

base

Contains a reference to the time base. You obtain a time base by calling the Movie Toolbox's GetMovieTimeBase or NewTimeBase functions.

If the time structure defines a duration, set this field to nil. Otherwise, this field must refer to a valid time base.

You specify the time value in a time structure in a 64-bit integer value as follows:

typedef Int64 CompTimeValue;

The Movie Toolbox uses this format so that extremely large time values can be represented. The Int64 data type defines the format of these signed 64-bit integers.

struct Int64
{
    long hi;    /* high-order 32 bits-value field in time structure */
    long lo;    /* low-order 32 bits-value field in time structure */
};
typedef struct Int64 Int64;

Field

Description

hi

Contains the high-order 32 bits of the value. The high-order bit represents the sign of the 64-bit integer.

lo

Contains the low-order 32 bits of the value.

The Fixed-Point and Fixed-Rectangle Structures

The Movie Toolbox matrix functions provide two mechanisms for specifying points and rectangles. Some of the functions work with standard QuickDraw points and rectangles, which use integer values to identify coordinates. Others, such as the TransformFixedRect function, work with points and rectangles whose coordinates are expressed as fixed-point numbers. By using fixed-point numbers in these points and rectangles, the Movie Toolbox can support a greater degree of precision when defining graphic objects.

The FixedPoint data type defines a fixed point. The FixedRect data type defines a fixed rectangle. Note that both of these structures define the x coordinate before the y coordinate. This is different from the standard QuickDraw structures.

struct FixedPoint
{
    Fixed x;        /* point's x coordinate as fixed-point number */
    Fixed y;        /* point's y coordinate as fixed-point number */
};
typedef struct FixedPoint FixedPoint;

Field

Description

x

Defines the point's x coordinate as a fixed-point number.

y

Defines the point's y coordinate as a fixed-point number.

struct FixedRect
{
    Fixed left;         /* x coordinate of upper-left corner */
    Fixed top;          /* y coordinate of upper-left corner */
    Fixed right;        /* x coordinate of lower-right corner */
    Fixed bottom;       /* y coordinate of lower-right corner */
};
typedef struct FixedRect FixedRect;

Field

Description

left

Defines the x coordinate of the upper-left corner of the rectangle as a fixed-point number.

top

Defines the y coordinate of the upper-left corner of the rectangle as a fixed-point number.

right

Defines the x coordinate of the lower-right corner of the rectangle as a fixed-point number.

bottom

Defines the y coordinate of the lower-right corner of the rectangle as a fixed-point number.

Media Handler Support

The video, base, and tween media handlers support sending their data to other tracks. Text data can also be sent, but none of the media handlers currently receive it. The sound, music and 3D media handlers do not support sending their data to other tracks.

Not all media handlers support all input types. Media handlers can decide which input types to support. Table 9-1 lists the input types supported by each Apple-supplied media handler.

Table 9-1  Input types supported by Apple-supplied media handlers

Input type

Video

Text

Sound

MPEG

Music

Sprite

Timecode

3D

Matrix

x

x

x

x

x

x

Graphics mode

x

x

x

x

x

x

Clip

x

x

x

x

x

x

Volume

x

x

x

 

Balance

x

x

x

 

Sprite image

x

x

3D sound

x

x

Data Handler Components

QuickTime introduced a memory-based data handler. This data handler component works with movie data that is stored in memory (referenced by a handle) instead of in a file. This data handler has a component subtype value of

HandleDataHandlerSubType ('hndl')

To create a movie that uses the handle data handler, set the data reference type to HandleDataHandlerSubType when you call the NewTrackMedia function. Note that the movie data in memory is not automatically saved with the movie. If you want to save the data that is in memory, use the FlattenMovie or InsertTrackSegment functions to copy the data from memory to a file. Note that there is a special flag for FlattenMovie and data handlers.

The handle data handler does not use aliases as its data reference, and therefore does not use alias handles. Rather, it uses 4-byte memory handles as its data reference. The data reference contains the actual handle that stores the needed data. If you pass a handle value of nilMovie Data Types, the data handler allocates and manages the handle for you. If you pass a handle value other than nilMovie Data Types, the data handler uses your handle. It is then your responsibility to manage the handle and dispose of it when appropriate. Note that a single handle may be shared by several data handler components. Whenever new data is added, the data handler resizes the handle to accommodate new data.

Support for Progressive Downloads

The QuickTime Movie Toolbox includes support for progressive downloads, which allow part of a movie to be displayed before all of its data has been received over a network or other slow link.

Applications that use the movie controller component provided by Apple automatically get support for progressive downloads. Applications that do not use the standard movie controller can use the two high-level functions for progressive downloads, QTMovieNeedsTimeTable and GetMaxLoadedTimeInMovie, to determine whether a movie is being progressively downloaded and, if so, to see how much of it has already been downloaded. Finally, the few applications that need even more control over progressive downloads, such as control over individual tracks or media, can use one or both of the low-level functions for progressive downloads, MakeTrackTimeTable and MakeMediaTimeTable.

Displaying a Progressively Downloaded Movie

Listing 9-1 illustrates how to use the QTMovieNeedsTimeTable function, to find out if a movie if being progressively downloaded, and the GetMaxLoadedTimeInMovie function, to find out how much of the movie has been downloaded.

Listing 9-1  Displaying a progressively downloaded movie

WindowPtr   movieWindow;
Movie       theMovie;
Boolean     needsTimeTable;
TimeValue   loadedTime = -1;
err = GetDisplayedMovie (&movieWindow, &theMovie);
err = QTMovieNeedsTimeTable (theMovie, &needsTimeTable);
if (needsTimeTable)
{
    err = GetMaxLoadedTimeInMovie (theMovie, &loadedTime);
    // Display the movie up to the current end
}

Low-Level Routines

Some applications may need more control over progressive downloads, such as control over individual tracks or media, than is possible with the high-level functions for progressive downloads. These applications can use one or both of the low-level functions for progressive downloads described in this section, MakeTrackTimeTable and MakeMediaTimeTable.

Handling Media Sample References

You could always use GetMediaSampleReference to access samples in a movie one at a time. QuickTime introduced GetMediaSampleReferences (note that this is the plural form of the GetMediaSampleReference function), which you can use to obtain information about groups of samples. QuickTime also introduced AddMediaSampleReferences, which you can use to work with groups of samples that have already been added to a movie.

Manipulating Media Input Maps

The Movie Toolbox contains two functions for maintaining media input maps: GetMediaInputMap and SetMediaInputMap.

Each track has particular attributes such as size, position, and volume associated with it. The media input map of that track describes where the variable parameters are stored so that modifier tracks know where to send their data. When a track is copied, its input map is also copied. CopyTrackSettings also transfers the media input map.