Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

VBR Sound Compression Support

QuickTime 6 adds support for using variable bitrate (VBR)-enabled sound compressor components. Both the QuickTime Movie exporter component available in the export dialog (also known as the ConvertMovieToFile API dialog) and the Standard Sound compression dialog component have been updated to use and to recognize VBR compressor components.

QuickTime 6 also provides QuickTime developers with the capability of building their own custom VBR-enabled sound compressor components, as discussed in this section.

In this section:

Background
QuickTime 6 VBR Support
Some Techniques For Compressing VBR Audio
Using the Standard Sound Compression Component and VBR Compression
Audio File Formats and VBR Compression
Doing Something with VBR Audio Data
New Tween Component API
Changes to Effects Dialog
QuickTime Effects Classes
QuickTime Effects Presets
None Codec Enhancements
Additional Still Image Metadata Support in Mac OS 9 and Windows
New APIs For Creating Exif Files
Improved Movie Toolbox Support for Data Handlers
OpenADataHandler Extended
Advanced APIs


Background

QuickTime 4.1 and the Sound Manager introduced support for the playback of VBR audio––in particular, VBR support for the decoding and playback of MP3 audio. A number of modern audio compression formats, such as MP3, either support or require VBR decoding.

Versions of QuickTime prior to QuickTime 4.1 provided support only for constant bitrate (CBR) audio. The fundamental difference between constant bitrate and variable bitrate audio is related to the rate at which audio data is presented to the sound decoder to generate sound.

In CBR audio, the rate is constant. If one second of audio requires 40 K bytes, then 5 seconds will require 200 K bytes (= 40 Kbytes/sec * 5 sec). Moreover, given a stream of 3 minutes of audio compressed like this, to start playing at 2:30, you would advance 6,000K into the stream.

With VBR audio, the data rate varies depending upon the complexity of the encoded sound. For example, a very quiet passage of a score could be compressed much more than a very exciting passage. A VBR encoder will analyze the audio and use the appropriate number of bits, varying its usage in the process. This means that the amount of data for a complex passage is greater than for a less complex passage. This also complicates locating data in the stream because the “road map” is located within the stream.

By way of analogy, video encoding formats are typically VBR in nature. A more complex image requires more bits than a less complex image. As different images are encoded, the number of bits required for each will vary. The analog to CBR audio in the video space is raw RGB or uncompressed YUV.

QuickTime 6 VBR Support

As discussed, QuickTime and the Sound Manager have been able to decode self-framed, variable bitrate formats such as MP3 since QuickTime 4.1. In addition, the QuickTime Movie file format has been able to carry variable bitrate audio.

With QuickTime 6, QuickTime and the Sound Manager add much richer and more comprehensive support for VBR audio, including support for both compression of VBR audio and decompression of non-self-framed VBR audio formats. An example of a non-self-framed audio format is AAC, described in the section “Defining AAC.” Table 1-2 shows the audio support available since QuickTime 4.1.

Table 1-2  VBR audio support in different versions of QuickTime

Version

VBR Audio

Support

QuickTime 6

Encode and decode, e.g., MP3

Non-self-framed VBR audio, e.g., AAC

QuickTime 5

Decode and playback

Self-framed VBR

QuickTime 4.1

Decode and playback, e.g., MP3

Self-framed VBR

Some Techniques For Compressing VBR Audio

This section discusses some of the techniques you can use if you need to compress VBR audio.

Because variable bitrate audio may contain audio frames of different sizes, it is important that an application use the appropriate APIs to generate the compressed audio. If, for example, your application receives a -213 (siVBRCompressionNotSupported) error from QuickTime or the Sound Manager, it indicates either QuickTime or the Sound Manager doesn’t “know” about VBR compression, or doesn’t believe your application understands VBR compression.

To inform QuickTime that your application understands the details of VBR compression, here are some steps that you should consider:

  1. To begin with, you must use the SoundConverterFillBuffer() API. If you are using the SoundConverterFillBuffer() API, you’ve already done most of the work. Although SoundConverterConvertBuffer() cannot be used for VBR compression, you can configure the SoundConverter without making a decision as to using FillBuffer or ConvertBuffer yet, in case you want to continue using the SoundConverterConvertBuffer() routine for fixed compression audio. There is no good reason to do so, but it may be important in your current implementation.

  2. Your application must inform the SoundConverter that it can handle VBR audio. To do this, immediately after opening the SoundConverter with SoundConverterOpen(), make a call to SoundConverterSetInfo(), passing the siClientAcceptsVBR selector like the following:

    SoundConverterSetInfo(theSoundConverter, siClientAcceptsVBR,(void*)true);

This lets the sound converter know that you are VBR compression-aware.

  1. After configuring the sound converter with compression parameters (if present), request the compressor’s compression information, so you know how many PCM samples are generated per audio frame.

  2. Ask for siCompressionFactor and look at the resulting CompressionInfo. If the compInfo.compressionID field is set to variableCompression, then the codec is configured to generate VBR audio. If it has another value, the codec is configured for a fixed bitrate––just as it would in versions of QuickTime prior to QuickTime 6. Remember that a single codec can support fixed and variable compression, so don’t assume its capabilities from its codec type.

Just as before, samplesPerPacket holds the PCM sample count per audio frame (packet). For VBR audio, you can ignore bytesPerFrame/bytesPerPacket, since the sizes aren’t constant.

  1. For variable compression codecs, you need to know the worst case size of a single audio frame (packet). You can then allocate the output buffer for use with the SoundConverterFillBuffer() routine, based on a multiple of this size. Failing to do this might result in SoundConverterFillBuffer() not being able to generate even a single audio frame. If you spin on SoundConverterFillBuffer() waiting for it to generate at least one audio frame before continuing but don’t provide a large enough output buffer, you have the makings of a really cool and involved infinite loop.

Use the new selector siCompressionMaxPacketSize to retrieve the worst case packet size. The following code shows an example:

    UInt32 maxPacketSize = 0;
 
    err = SoundConverterGetInfo( theSoundConverter,
                                siCompressionMaxPacketSize,
                                &maxPacketSize );

If a VBR codec doesn’t support this selector, you may want to use a worst case output buffer size such as 32K.

Note: VBR codec developers should implement this selector. This will not be implemented by fixed bitrate compressors, although it is not illegal to do so.

  1. Use SoundConvertFillBuffer() to perform the encoding, as shown in the code below. The value should be tied to the codec’s current configuration.

        err = SoundConverterFillBuffer(theSoundConverter, //a sound converter
                fillBufferUPP,          // proc
                fillBufferRefCon,       // refCon passed to FillDataProc
                soundOutputBuffer,      // compressed audio buffer
                soundOutputBufferSize,  // size of compressed audio buffer
                &actualOutputBytes,     // number of output bytes
                &outputFrames,          // number of output frames
                &outputFlags);          // fillbuffer returned advisory flags

The difference with VBR compression is that each call only returns audio, where all the frames have the same size in bytes. This is necessary because the SoundConverterFillBuffer() API returns the number of bytes it wrote and the number of frames but doesn’t return any kind of array indicating the boundaries between frames. If you divide actualOutputBytes by outputFrames, you can determine how large each audio frame is.

As an example, if the audio frames have the following sizes in bytes

[  40  ] [   40  ] [    50    ] [    50   ] [    50    ] [ 30 ] [  40  ]

at least four calls to SoundConverterFillBuffer will be necessary in order to encode these frames. This call would return the following values:

actualOutputBytes        outputFrames
-----------------       ------------
    80                      2
    150                     3
    30                      1
    40                      1

Using the Standard Sound Compression Component and VBR Compression

Like the SoundConverter, QuickTime doesn’t want to offer VBR sound compressors to applications that cannot support them. This means that if your application uses the Standard Sound Compression dialog to select and configure sound compressors, you should pass the new (in QuickTime 6) scSoundVBRCompressionOK selector to SCSetInfo() as in the following code example:

    ComponentInstance ci = OpenDefaultComponent(StandardCompressionType,
                                        StandardCompressionSubTypeSound);
    if (ci ) {
                Boolean doVBR = true;
 
                SCSetInfo (ci, scSoundVBRCompressionOK, &doVBR);
                . . .

If you don’t pass the new scSoundVBRCompressionOK selector to SCSetInfo(), only fixed compression codecs will be presented in the list.

In fact, compressors that perform fixed and variable compression will be presented if this selector is not called, but those compressors will only offer their fixedCompression options. Since AAC only performs variable compression, it will not appear in the dialog unless you call SCSetInfo with scSoundVBRCompressionOK.

In QuickTime 6, a new Standard Compression selector is provided in QuickTimeComponents.h that returns a list of available codecs. The selector, a pointer to a handle, is defined as follows:

scAvailableCompressionListType = FOUR_CHAR_CODE('avai')

This is the same kind of handle as the existing scCompressionListType selector. Applications that need to build lists of codecs (compressors) for their user interface should adopt this API. If the scAvailableCompressionListType selector is not recognized, use the previous code.

Audio File Formats and VBR Compression

Not all audio file formats can hold variable compression audio, since the information about framing isn’t always available in every format.

QuickTime Movies provide a format that can hold the information, just as MPEG-4 files can. AIFF and WAVE, however, are formats that do not carry such information.

This explains why you see the MPEG-4 audio codec available in the QuickTime Movie exporter’s sound options––but not in the AIFF options. Not surprisingly, these exporters use the Standard Sound Compression dialog as above. Because VBR compression is opted in by the client, only the QuickTime Movie exporter passes the scSoundVBRCompressionOK selector.

Doing Something with VBR Audio Data

At this point in the process, your application is either generating VBR audio to be stored in a QuickTime Movie for playback later, or you want to play or decode the audio directly. Of course, you may be using your own format to store the audio, but remember, you need to store the framing information yourself.

If you store the data in the QuickTime Movie, you need to store the generated audio frames in a way that is compatible with how QuickTime stores VBR audio in sound tracks.

To play or decode the audio, you need to use the additional fields in the ExtendedSoundComponentData, ExtendedScheduledSoundHeader, or ExtendedSoundParamBlock, depending on how you are playing the data. Fortunately, they are the same fields.

The following fields are introduced in QuickTime 6:

    long frameCount;        // number of audio frames
    long * frameSizesArray; // pointer to array of longs with frame sizes
                                // in bytes
    long commonFrameSize;   // size of each frame if common

Specifically, frameCount, frameSizesArray and commonFrameSize are relevant for playback and decoding of AAC audio, as well as for other non-self-framed audio VBR audio formats.

As discussed earlier, QuickTime versions prior to QuickTime 6 could handle self-framed VBR audio. This is why the existing extended bufferSize field is sufficient for MP3 audio. AAC audio, though, doesn’t have information within it to indicate framing, and depends upon out-of-band data to carry that information. In the case of QuickTime and MPEG-4 movies, that information is in the sample tables.

The fields just described (new in QuickTime 6) are used to convey the information to the audio decoder (or sound decompressor in Sound Manager parlance) and are necessary for use with AAC audio. In all cases, these fields all describe a single buffer of audio. The existing sampleCount, buffer and bufferSizes fields all must be valid.

In addition, either frameCount and frameSizesArray or commonFrameSize must be valid (indicated by extendedFlags) in order to decode AAC data. (Note that frameCount and frameSizesArray must be valid as a unit because they work together, not as separate fields.)

The flags for extendedFlags are in the header file Sound.h as follows:

    kExtendedSoundFrameSizesValid = 1L << 2,
                        // set if frameSizesArray is valid
                        // (this will be nil if all sizes are common and
                        // kExtendedSoundCommonFrameSizeValid is set)
 
    kExtendedSoundCommonFrameSizeValid = 1L << 3,
                        // set if all audio frames have the same size and
                        // the commonFrameSize field is valid

If commonFrameSize is set, this means that all audio frames in the VBR buffer have exactly the same size in bytes. There is no frame count, since bufferSize divided by commonFrameSize is the frame count.

If frameCount and frameSizesArray are valid (remember, these fields must be considered as a unit), then frameCount holds a count of the number of elements in the frameSizesArray array. This array is a set of 32-bit values holding the size of each audio frame. In the above example, the fields would look like this:

    frameCount = 7;
    frameSizeArray = -->   { 40, 40, 50, 50, 50, 30, 40 }

Note: The frameCount and frameSizesArray fields will be updated by the decoder, so you should not allocate a pointer and store that in frameSizesArray and expect to be able to deallocate it when done. Instead, allocate the pointer and store a copy of the address in frameSizesArray.

Just as you can use the SoundConverterFillBuffer() routine to encode VBR audio, you can also use it to decode AAC audio. However, the SoundConverterFillBufferDataProc’s returned ExtendedSoundComponentData must set the appropriate flags, including the fields described above.

New Tween Component API

In QuickTime 6, tween components now provide an interrupt-safe interface using a new API routine, QTDoTweenPtr. This new call provides for return values in a pointer rather than a handle. Some specific tweens implemented as components required changes to ensure their interrupt safeness. Not all Apple-defined tween components support this new API. However, all of those needed for effects have been so revised.

QTDoTweenPtr

Runs a tween component, providing for return values in a pointer rather than a handle.

OSErr QTDoTweenPtr (QTTweener tween,
TimeValue atTime,
Ptr result,
long resultSize) ;

Parameters
tween

A tween to be run.

atTime

A value that defines the time to run the tween.

result

The result of the tweening operation.

resultSize

The size of the result returned.

Discussion

This routine is an interrupt-safe version of the QTDoTween routine, which also runs a tween component. Note that it has the following limitations:

Introduced in QuickTime 6.

Availability
Declared In
Movies.h

C interface file: Movies.h

Changes to Effects Dialog

In QuickTime 6, the effects dialog has been revised and enhanced. The new features include


Figure 1-11  A new effects dialog in Mac OS X with sliders and menu items

Figure 1-11 A new effects dialog in Mac OS X with sliders and menu items

Custom Effect Controls

Effects may choose to implement custom controls to allow the user to more easily edit complex parameters that are ill-served by simple sliders or type in boxes. Effects may allow a custom control for either a single parameter, or for a group of parameters.

Parameter(s) for a custom control must still be data types defined by the standard set, or for complex records of data, must be defined within a group as individual parameters made up from base data types (for example, a point is a group containing two Fixed point numbers).

This is to allow applications that do not wish to use the custom control for the effect to set values themselves.

Effects should be aware that these custom controls may be deployed by the application in either a dialog or a window, with application-defined background colors or patterns, along with application-defined font characteristics for the window.

It is recommended that an effect implement custom controls only when needed, and that custom controls be used for specific types of parameters (i.e., point, rectangle, polygon, path) rather than the entire user interface for the effect. Effects may choose to implement multiple custom controls that combine with standard controls to present the total user interface.

For effects that have very complex user interfaces not well suited for inclusion within a single window, it is recommended to use kParameterImageIsPreset––which allows the effect to have an external editing application for parameters that may then be set within the standard User Interface via the open file dialog or drag and drop. The Lens Flare (shown in Figure 1-12) effect’s “Flare Type” is an example of such a preset.


Figure 1-12  A new Lens Flare effect dialog in Mac OS X

Figure 1-12 A new Lens Flare effect dialog in Mac OS X

New Behavior Flag kCustomControl Added

For parameters that use a custom control to control a single parameter value, a new behavior flag has been added (kCustomControl), and the behavior for the parameter should be kParameterItemControl.

For parameters that are groups, the same flag (kCustomControl) should be used, and the behavior should be kParameterItemGroupDivider. Groups with the kCustomControl bit set will be implemented by calling the custom control for that group––the parameters within that group will not be processed in the normal manner.

In both cases, the new customType and customID fields of the behavior must be filled in. These are used in order to allow your custom control to determine which parameter is being edited in the case where the custom control is used for the editing of multiple parameters. These values are passed into the pdActionCustomNewControl call. Since the custom control mechanism is also used by QuickTime’s default effect dialogs, you should be prepared to pass onto the base effect any pdActionCustomNewControl calls for type/id pairs that you do not handle yourself. When pdActionCustomNewControl is called for controls of types handled by QuickTime, customType is kParameterAtomTypeAndID and customID is the ID of the parameter atom.

Using pdActionCustomNewControlControl to Create New Custom Controls

pdActionCustomNewControlControl is called by the application to create a new custom control or set of controls for an effect parameter. When pdActionCustomNewControl is called, the effect should perform any basic allocation it needs for storage and return the result in storage. The options parameter tells the control if the application wishes to support interpolated, optionally interpolated, or a single value parameter.

Since pdActionCustomNewControlControl may call upon your effect for other items within the dialog, it is recommended that your effect have an easy way to determine which controls it implements by using one of these two techniques:

When pdActionCustomDisposeControl is called, any allocation done by the control should be disposed of. In addition, pdActionCustomDisposeControl is the last chance the control has to commit any user changes into the sample.

Controls that implement type-in fields typically need to commit any final user edits at this time.

struct QTCustomControlNewRecord {
    void * storage; /* storage allocated/disposed by the control*/
    QTParameterDialogOptions options; /* options used to control
                                            interpolation/not*/
    QTAtomContainer sample; /* sample that holds the data to be edited*/
    long customType; /* custom type and ID specified by effect for
                        creation of this control*/
    long customID;
};
typedef struct QTCustomControlNewRecord QTCustomControlNewRecord;
typedef QTCustomControlNewRecord *      QTCustomControlNewPtr;

pdActionCustomPositionControl is called by the application to position the control within a window or dialog.

The control should determine if it will fit in the allotted area and position itself there. It should also return the space taken up by the control. Note you are free to implement controls which are variable in size depending upon which parameter you are editing. You don’t need to scale your control to the requested size. If the area presented to your control is too small, set didFit to FALSE. You should still return in used the size you would have liked to use for the control. The application will then try again with a new size. Note that all controls must be able to fit within a minimum of 300 by 250 pixels.

Displaying Text Properly in Application Windows

Custom controls that draw text should make note of the text font, size, and style at this time in order to properly display within application windows.

Note that the default state for the control is hidden. You will receive a pdActionCustomShowHideControl in order to enable your control. You should not draw your control in response to pdActionCustomPositionControl.

struct QTCustomControlPositionControlRecord {
    void * storage; /* storage for the control*/
    WindowPtr window; /* window to be used by the control*/
    Rect location; /* location within the window the control may use*/
    Rect used; /* returned by the control to indicate size it actually
                used*/
    Boolean didFit; /* did the control fit in the specified area?*/
    Boolean pad[3];
};
typedef struct QTCustomControlPositionControlRecord QTCustomControlPositionControlRecord;
typedef QTCustomControlPositionControlRecord * QTCustomControlPositionControlPtr;

pdActionCustomShowHideControl is called when the application wishes to enable/disable your control, or completely disable drawing of the control.

Your control should make note of the new state (if different from the last) and perform an InvalRect() on your drawing area, or you may draw your control’s initial state in the case of show. You should not attempt to erase your control as the result of a hide. Instead, call InvalRect() and allow the application to process the resulting event as appropriate.

struct QTCustomControlShowHideControlRecord {
    void * storage; /* storage for the control*/
    Boolean show; /* display the control?*/
    Boolean enable; /* enable the control (ie, black vs gray display)*/
    Boolean pad[2];
};
typedef struct QTCustomControlShowHideControlRecord QTCustomControlShowHideControlRecord;
 
typedef QTCustomControlShowHideControlRecord * QTCustomControlShowHideControlPtr;
Using pdActionCustomHandleEvent To Process Events

pdActionCustomHandleEvent is called to allow your custom control to process events.

Typical controls handle the following events:

If your control handles the entire event, set didProcess to TRUE. If you handled the event, but other controls still need the event, set didProcess to FALSE.

If your control supports the concept of focus for the purposes of typing (such as by having a type-in box for the parameter), then you set the tookFocus Boolean as part of your processing of the event. It is assumed that your control will draw the appropriate focus user interface as a result, and the calling application will disable any focus drawing within the remainder of the user interface.

By default, custom controls are not given idle time. If you need idle time, set needIdle to TRUE in response to the event that causes you to need idle (typically the taking of focus, or the first draw).

Your control will continue to be given idle events until you set needIdle to FALSE in response to a nullEvent.

struct QTCustomControlHandleEventRecord {
    void * storage; /* storage for the control*/
    EventRecord * pEvent; /* event to process*/
    Boolean didProcess; /* did we process entire event?*/
    Boolean tookFocus; /* did we take focus as a result of this event
                        (typically mouseDowns)*/
    Boolean needIdle; /* does this control need idle events?*/
    Boolean didEdit; /* did we edit the samples?*/
};

typedef struct QTCustomControlHandleEventRecord QTCustomControlHandleEventRecord;

typedef QTCustomControlHandleEventRecord * QTCustomControlHandleEventPtr;

Using pdActionCustomSetFocus to Set or Advance Current Focus

pdActionCustomSetFocus is called in order to set or advance the current focus of the user interface, typically because the user has pressed the tab or shift-tab keys, or because the user clicked within the area defined by your control.

Your control will be called with pdActionFocusFirst, pdActionFocusLast, or pdActionFocusOff to set or clear focus on your control. Your control will be called with pdActionFocusForward or pdActionFocusBackward to cycle focus within your control (if your control has multiple focus). If your control does not support focus, or the focus request results in focus moving beyond your supported range, return pdActionFocusOff in the focus parameter. Otherwise, return the focus that you set.

Controls which have no focus would always set focus to be pdActionFocusOff.

Controls with a single focus would set pdActionFocusFirst when requested to set either pdActionFocusFirst or pdActionFocusLast, and would set pdActionFocusOff for either pdActionFocusForward or pdActionFocusBackward.

enum { pdActionFocusOff = 0, /* no focus */ pdActionFocusFirst = 1, /* focus on first element */ pdActionFocusLast = 2, /* focus on last element */ pdActionFocusForward = 3, /* focus on next element */ pdActionFocusBackward = 4 /* focus on previous element */ }; struct QTCustomControlSetFocusRecord { void * storage; /* storage for the control*/ long focus; /* focus to set, return resulting focus*/ }; typedef struct QTCustomControlSetFocusRecord QTCustomControlSetFocusRecord; typedef QTCustomControlSetFocusRecord * QTCustomControlSetFocusPtr;

Using pdActionCustomSetEditMenu To Locate The Edit Menu

pdActionCustomSetEditMenu will be called to inform your custom control of the location of the edit menu.

If your control has editing boxes, this is useful in order to allow the user to perform cut, copy, and paste operations when focus is on one of these boxes.

struct QTCustomControlSetEditMenuRecord {
    void * storage; /* storage for the control*/
    MenuHandle editMenu; /* edit menu, or NIL*/
};
typedef struct QTCustomControlSetEditMenuRecord QTCustomControlSetEditMenuRecord;
 
typedef QTCustomControlSetEditMenuRecord * QTCustomControlSetEditMenuPtr;
Using pdActionCustomSetPreviewPicture To Preview Information

pdActionCustomSetPreviewPicture is called to inform your custom control of preview information that you may wish to use in the drawing of your user interface.

struct QTCustomControlSetPreviewPictureRecord {
    void * storage; /* storage for the control*/
    QTParamPreviewPtr preview; /* preview to set*/
};
typedef struct QTCustomControlSetPreviewPictureRecord QTCustomControlSetPreviewPictureRecord;
typedef QTCustomControlSetPreviewPictureRecord * QTCustomControlSetPreviewPicturePtr;

pdActionCustomSetEditCallout tells your control of the need by the application to be informed of changes to the parameter values (typically for the purposes of updating previews).

If a callout is available, your custom control should call it whenever a change has been made to the parameter(s) that your control is editing (as a result of user actions, most typically). If you choose not to implement this, live dragging or updating of values will not work.

struct QTCustomControlSetEditCalloutRecord {
    void * storage; /* storage for the control*/
    QTParamPreviewCalloutPtr callout; /* requested callout, or NIL to
                                        disable*/
};
typedef struct QTCustomControlSetEditCalloutRecord QTCustomControlSetEditCalloutRecord;
 
typedef QTCustomControlSetEditCalloutRecord * QTCustomControlSetEditCalloutPtr;
Using pdActionCustomGetEnableValue to Enable or Disable Other Controls

pdActionCustomGetEnableValue allows you to return a value for the purposes of enabling or disabling other controls.

Most custom controls do not need to implement this call.

If your control is able to control the enabling and disabling of other parameter controls (such as is done by standard pop up or enumerated type controls), you need to supply a value that can be use for greater than or less than types of comparisons.

struct QTCustomControlGetEnableValueRecord {
    void * storage; /* storage for the control*/
    long currentValue; /* value to compare against for enable/disable
                        purposes*/
};
typedef struct QTCustomControlGetEnableValueRecord QTCustomControlGetEnableValueRecord;
 
typedef QTCustomControlGetEnableValueRecord * QTCustomControlGetEnableValuePtr;
Using pdActionCustomSetSampleTime to Specify Duration and Start Time

pdActionCustomSetSampleTime tells your control information from the application about the duration and start time for the sample being edited.

Most controls do not need this information, but some may choose to use it in the interface they present the user. However, this call need not be made by applications, so the custom control should be prepared to run when the sample time information is not available.

struct QTCustomControlSetSampleTimeRecord {
    void * storage; /* storage for the control*/
    QTParamSampleTimePtr sampleTime; /* sample time information or NIL*/
};
typedef struct QTCustomControlSetSampleTimeRecord QTCustomControlSetSampleTimeRecord;
 
typedef QTCustomControlSetSampleTimeRecord * QTCustomControlSetSampleTimePtr;

pdActionCustomGetValue tells your control to store any value(s) into the specified atom container.

All custom controls must implement this call.

struct QTCustomControlGetValueRecord {
    void * storage; /* storage for the control*/
    QTAtomContainer sample; /* sample to store into*/
};
typedef struct QTCustomControlGetValueRecord QTCustomControlGetValueRecord;
 
typedef QTCustomControlGetValueRecord * QTCustomControlGetValuePtr;
Using pdActionCustomDoEditCommand to Handle Edit Commands

pdActionCustomDoEditCommand tells your control to handle edit commands if it allow focus and type in boxes.

All custom controls must implement this call if they support edit boxes.

struct QTCustomControlDoEditCommandRecord {
    void * storage; /* storage for the control*/
    long command; /* command to execute, return 0 here if processed*/
};
typedef struct QTCustomControlDoEditCommandRecord QTCustomControlDoEditCommandRecord;
 
typedef QTCustomControlDoEditCommandRecord * QTCustomControlDoEditCommandPtr;
typedef long QTParameterDialog;
enum {
    elOptionsIncludeNoneInList  = 0x00000001 /* "None" effect is included
                                                in list */
};
typedef long QTEffectListOptions;
enum {
    pdOptionsCollectOneValue = 0x00000001, /* should collect a single
                                            value only*/
pdOptionsAllowOptionalInterpolations = 0x00000002, /* non-novice
                                    interpolation options are shown */
pdOptionsModalDialogBox = 0x00000004, /* dialog box should be modal */
pdOptionsEditCurrentEffectOnly = 0x00000008, /* List of effects will not
                                                be shown */
pdOptionsHidePreview = 0x00000010 /* Preview item will not be shown */
enum {
    effectIsRealtime = 0 /* effect can be rendered in real time */
};

The following is a new API introduced in QuickTime 6.

QTGetEffectsListExtended

Provides for more advanced filtering of effects to be placed into the effect list.

QTGetEffectsListExtended (QTAtomContainer * list,
   long minSources,
   long maxSources,
   QTEffectListOptions getOptions,
   OSType majorClass,
   OSType minorClass,
   QTEffectListFilterUPP filterProc,
   void * filterRefCon);

Parameters
list

The effect list returned here.

minSources

The minimum number of sources that an effect must have to be added to the list. Pass –1 as this parameter to specify no minimum.

maxSources

The maximum number of sources that an effect can have to be added to the list. Pass –1 as this parameter to specify no maximum. The minSources and maxSources parameters allow you to restrict which effects are returned in the list, by specifying the minimum and maximum number of sources that qualifying effects can have.

getOptions

The options for populating the list.

majorClass

The major class to include, 0 for all.

minorClass

The minor class to include, 0 for all.

filterPro

Additional client filtering.

filterRefCon

A reference constant for the filter proc.

Discussion

This routine provides for more advanced filtering of effects to be placed into the effect list. Applications can filter on:

The callback is called for each effect which passes the other criteria for inclusion. If the callback returns a TRUE result, the effect is included in the list.

Note that your filter proc may receive multiple effects from various manufacturers. If you return TRUE for multiple effects of a given type, only the one with the higher parameter version number will be included.

If you wish other filtering such as effects from a given manufacturer, you can do this by returning FALSE for the other effects and TRUE for those that you prefer.

typedef CALLBACK_API( Boolean, QTEffectListFilterProcPtr )(Component
effect, long effectMinSource, long effectMaxSource, OSType majorClass, OSType minorClass, void *refcon);
typedef STACK_UPP_TYPE(QTEffectListFilterProcPtr)   QTEffectListFilterUPP;

Introduced in QuickTime 6.

QTGetEffectsList, which returns a QT atom container holding a list of the currently installed effects components.

Availability
Declared In
Movies.h

C interface file: Movies.h

QuickTime Effects Classes

With an ever-increasing number of effect components, it has become difficult for applications and users to navigate through the list. This section documents upcoming atoms that can be used for tagging effects into useful categories.

This will be of use to developers of applications that supply custom effect picking UI. It will also be of use for developers of effect components. Two groupings for effects are here defined: Major Class and Minor Class.

Major Class

The Major Class for an effect defines the purpose of an effect to allow applications to perform better filtering. It is not intended that the user see effects grouped by major class. For example, a two source effect might be given a major class of kTransitionMajorClass, which allows applications to tell the difference between two source effects that perform a transition vs. those that perform operations such as Chroma Key. Some applications may wish to exclude all effects that are not transitions.

Effects supply information about their Major Class through the use of an atom that can be found within their Effect Parameter Description atom container. Applications can read in this atom to determine the Major Class of a particular Effect.

    #define kEffectMajorClassType       'clsa'
    #define kEffectMajorClassID         (1)

The following are the defined legal values for the Major Class atom. Effects that fail to include a kEffectMajorClassType will be classified as kMiscMajorClass. Developers who feel their effect requires a new Major Class should contact Apple. Because Major Classes are used for filtering by applications, any extensions will need to be documented before they can become useful.

    #define kGeneratorMajorClass        'genr'  // zero source effects
    #define kFilterMajorClass           'filt'  // one source effects
    #define kTransitionMajorClass       'tran'  // multisource morph
                                                // effects
    #define kCompositorMajorClass       'comp'  // multisource layer
                                                // effects
    #define kMiscMajorClass             'misc'  // all other effects

Minor Class

Like the Major Class, the Minor Class of an effect serves to group the effect into a more refined definition. Unlike the Major Class, however, the Minor Class is intended to be used for grouping for the purposes of User Interface presentation. It is not intended that the Minor Class should be used for limiting the list of effects that a user might see––that is the purpose of the Major Class.

Effects supply information about their Minor Class through the use of an atom that can be found within their Effect Parameter Description atom container. Applications can read in this atom to determine the Minor Class of a particular Effect.

    #define kEffectMinorClassType       'clsi'
    #define kEffectMinorClassID         (1)

The following are Apple-defined values for the Minor Class atom, along with the recommended name to be used for display purposes. Effects that fail to include a kEffectMinorClassType will be classified as kMiscMinorClass. Effects are free to define their own Minor Classes, although Apple recommends that standard values be used if at all possible.

    #define kGeneratorMinorClass        'genr'  // "Generators"
    #define kRenderMinorClass           'rend'  // "Render"
    #define kFilterMinorClass           'filt'  // "Filters"
    #define kArtisticMinorClass         'arts'  // "Artistic
    #define kBlurMinorClass             'blur'  // "Blur"
    #define kSharpenMinorClass          'shrp'  // "Sharpen"
    #define kDistortMinorClass          'dist'  // "Distort"
    #define kNoiseMinorClass            'nois'  // "Noise"
    #define kAdjustmentMinorClass       'adst'  // "Adjustments"
    #define kTransitionMinorClass       'tran'  // "Transitions"
    #define kWipeMinorClass             'wipe'  // "Wipes"
    #define k3DMinorClass               'pzre'  // "3D Transitions"
    #define kCompositorMinorClass       'comp'  // "Compositors"
    #define kEffectsMinorClass          'fxfx'  // "Special Effects"
    #define kMiscMinorClass             'misc'  // "Miscellaneous"

Effects that don’t fit into the above listed groupings can supply another value for their Minor Class. However, it is likely that these effects will want to have a user visible name to go along with their class. The name is supplied by another atom, which should contain a Pascal string that is the name of the minor class. If the minor class is one which already has a standard name, this atom will be ignored.

    #define kEffectMinorClassNameType   'clsn'
    #define kEffectMinorClassNameID     (1)

QuickTime Effects Presets

Some effects with complex parameters would like to provide the user with groups of useful parameter values that can be easily selected. This section documents an optional mechanism that can be used by effects to define these “presets.” Applications may also use these presets to present to the user a list of selectable effect parameters.

Atom Contents

Like most options within effects, the presets are defined through the use of atoms present within the Effect Parameter Description atom container. Effects may define any number of presets, with the atom type being kEffectPresetType and the ID being numbers from 1 to N (where N is the number of presets).

Within each preset, three child atoms are found:

    #define kPresetNameType                 'pnam'
    #define kPresetNameID                   (1)
    #define kPresetPreviewPictureType       'ppct'
    #define kPresetPreviewPictureID         (1)
    #define kPresetSettingsType             'psst'
    #define kPresetSettingsID               (1)

The preset name defines the name of the preset as a Pascal string. The preset preview picture defines the image to be displayed to the user as a picture with a minimum size of 86 by 64 pixels. The preset settings atom contains within it all of the parameter values that define a particular preset.

Example Effect 'atms' Resource

This example shows the presets present in the Slide effect that define a Top and Bottom directed slide. The example is a portion of the 'atms' resource and demonstrates how to define these presets through the use of Rez.

// atom type       ID Child count
kEffectPresetType, 1, 3,
    {
    };
    kPresetNameType, kPresetNameID, noChildren,
        {
        string { "Top" };
        };
    kPresetPreviewPictureType, kPresetPreviewPictureID, noChildren,
        {
        lstring {
            $"08A0 0000 0000 0040 0056 0011 02FF 0C00"
            /* MORE PICTURE DATA HERE */
            $"7FE0 03AB 7FE0 03AB 7FE0 03AB 7FE0 00FF"
            };
        };
    kPresetSettingsType, kPresetSettingsID, 2,
        {
        };
        'pcnt', 1, 2,
            {
            };
            'twnt', 1, noChildren,
                {
                kParameterTypeDataFixed;
                };
            'data', 1, noChildren,
                {
                long { "0" };
                long { "65536" };
                };
        'angl', 1, noChildren,
            {
            Fixed { "0.0" };
            };
 
// atom type       ID Child count
kEffectPresetType, 2, 3,
    {
    };
    kPresetNameType, kPresetNameID, noChildren,
        {
        string { "Bottom" };
        };
    kPresetPreviewPictureType, kPresetPreviewPictureID, noChildren,
        {
        lstring {
        $"083C 0000 0000 0040 0056 0011 02FF 0C00"
        /* MORE PICTURE DATA HERE */
        $"0277 BF42 1F08 5FE8 001F 00FF"
            };
        };
    kPresetSettingsType, kPresetSettingsID, 2,
        {
        };
        'pcnt', 1, 2,
            {
            };
            'twnt', 1, noChildren,
                {
                kParameterTypeDataFixed;
                };
            'data', 1, noChildren,
                {
                long { "0" };
                long { "65536" };
                };
        'angl', 1, noChildren,
            {
            Fixed { "180.0" };
            };

None Codec Enhancements

QuickTime 6 includes an improved None codec (also known as the Raw codec because it deals with manipulations of uncompressed pixels). The new version provides the following enhancements:

In QuickTime 5.0.x and before, the None codec would always use point sampling. The new version uses point sampling in the fastest, lowest-quality mode, bilinear interpolation in a slower, medium-quality mode, and bicubic anti-aliasing in the slowest, highest-quality mode.

The enhanced None codec introduces two new quality levels beyond the point-sampling quality provided in the previous None codec:

This quality is especially apparent in

(1) rotation,

(2) perspective,

(3) image size reduction, and

(4) image size zooming.

Bilinear interpolation is available with codecHighQuality.

codecMaxQuality yields either bicubic anti-aliasing or bicubic interpolation, depending on the complexity of the transformation: anti-aliasing is currently only available with pure scaling operations, not rotation or perspective. The anti-aliasing is designed to meet or exceed the quality produced by Adobe PhotoShop. When specifying codecNormalQuality, point-sampling is used.

When doing minor size changes or phase changes, there is little apparent difference in quality between bilinear and bicubic interpolation: the primary difference is in sharpness and contrast. This is especially noticeable after multiple generations of processing, where bilinear processing will lose sharpness and contrast, whereas bicubic interpolation tends to preserve it.

When zooming up by a factor of 4 or more, bilinear interpolation suffers from “stellation”: where stars are superimposed on the pixels. Bicubic interpolation yields more natural, rounded, smooth features without artifacts.

When decimating an image (that is, reducing its size), bicubic anti-aliasing produces the best possible quality. Bilinear interpolation can yield acceptable quality if only shrinking a small amount, but decimation by greater than a factor of 2 will cause aliasing, which is manifested as jaggies, disappearing detail, and “popping pixels.”

As expected, higher quality comes at a price. With point-sampling (codecNormalQuality) taking 1 T seconds, the others take approximately:

Using a higher quality may have a negative effect on frame rate, especially on older machines. Typically, codecMaxQuality is to be used for off-line, non-real-time applications, whereas codecHighQuality can be used successfully for real-time applications on faster machines. You might want to check the frame rate and throttle the quality as appropriate. Even faster machines can benefit from this throttling, because their frame rate can suffer on higher resolution images.

The new enhanced None codec is a complete implementation of its component interface. Complete implementation is defined as:

Pixel formats:

(Note that formats flagged with an asterisk (*) are only available on Windows).

Transfer modes:

Alpha-premultiplied-to-black is the fastest of the alpha compositing modes. For example, it is possible to transform a 32 bit ARGB PixMap by a 3x3 perspective transformation, interpolating it with bicubic interpolation, and alpha-compositing it to an 8-bit color-mapped PixMap––directly––one-pass.

More pixel formats (1, 2 and 4 bits) are supported, but in a less than desirable way, by relying on CopyBits and multiple instantiations of the enhanced None codec. Other transfer modes (for example, XOR) are feebly supported in the same manner.

Alpha is a first class component of 32 bit pixels. The previous None codec sometimes behaved badly with the alpha component, but the enhanced None codec preserves it and involves it in computations. The result of an alpha composition has a meaningful alpha component, which can then be used as a source for a subsequent alpha composition; using this, rendering can be optimized by caching partial composites of the static portions of scenes, requiring only the dynamic portions to be composited individually. From an architectural viewpoint, these alpha operations lend themselves then to a composition tree or DAG (directed acyclic graph), rather than a simple composition pipeline as limited in the previous None codec. This comes at no additional computational cost.

The enhanced None codec in QuickTime 6 is typically invoked using:

and other calls.

Unlike the previous None codec, there is a negligible penalty for startup, and matrix changes. In particular, the matrix can be changed every frame with no degradation of the frame rate. Thus, it can be used for immersive imaging applications, where a series of images are embedded in 3D.

For more information, see Ice Floe Note #23 at

http://developer.apple.com/quicktime/icefloe/dispatch023.html

The new enhanced None codec can be used as a general texture-mapped rendering and compositing engine, when accessed directly through the API. However, it is also invoked automatically by the Image Compression Manager (ICM) to assist other codecs, by the Sprite Media to implement animation, and by others.

Additional Still Image Metadata Support in Mac OS 9 and Windows

The JPEG and TIFF graphics exporters should be able to create Exif files containing application-specified metadata and thumbnail images. QuickTime for Mac OS X (10.1) provided this support, which is now also available in Mac OS 9 and Windows.

Indexed Image Types

Several graphics importers support access to individual images within a multiple-image file. By using the GraphicsImportGetImageCount and GraphicsImportSetImageIndex routines, you can select an individual layer from a Photoshop file, or an individual resolution from a multi-resolution FlashPix file, for example. However, there has not been a way to distinguish between different types of indexed images: thumbnail, layer, page, resolution, etc. Although applications can sometimes use the file type to suggest the interpretation, this inhibits them from being able to take full advantage of new third-party graphics importers. Furthermore, some formats, such as TIFF, can support a variety of indexed image types.

The user data type kQTIndexedImageType has now been defined for graphics importers to indicate what a particular indexed image is. The following sample code shows how to determine whether the second image in a file is a thumbnail.

Boolean IsSecondImageThumbnail( GraphicsImportComponent gi )
{
    OSErr err;
    unsigned long saveIndex = 1;
    UserData userData = nil;
    Handle h = nil;
    Boolean isThumbnail = false;
    long count, i;
 
    GraphicsImportGetImageIndex( gi, &saveIndex );
    err = GraphicsImportSetImageIndex( gi, 2 );
    if( err ) goto bail;
    err = NewUserData( &userData );
    if( err ) goto bail;
    err = GraphicsImportGetMetaData( gi, userData );
    if( err ) goto bail;
    h = NewHandle( 0 );
    err = MemError();
    if( err ) goto bail;
    err = GetUserData( userData, h, kQTIndexedImageType, 1 );
    if( err ) goto bail;
    // Is kQTIndexedImageIsThumbnail present in the list?
    count = GetHandleSize( h ) / sizeof( OSType );
    for( i = 0; i < count; i++ ) {
        if( EndianU32_NtoB(kQTIndexedImageIsThumbnail) == ((OSType *)*h)[ i ] ) {
            isThumbnail = true;
            break;
        }
    }
 
bail:
    if( userData ) DisposeUserData( userData );
    if( h ) DisposeHandle( h );
    GraphicsImportSetImageIndex( gi, saveIndex );
    return isThumbnail;
}

Alpha Modes

The user data type kQTAlphaMode has been defined to allow graphics importers to indicate the recommended interpretation of an image’s alpha channel, if known. For example, a graphics importer could indicate that the image data has been premultiplied with the alpha channel against a black background by reporting a metadata item of type kQTAlphaMode and value graphicsModePreBlackAlpha. If the image data has not been premultiplied, it would report graphicsModeStraightAlpha.

Image Data

User Data Type

Not premultiplied

graphicsModeStraightAlpha

Premultiplied with alpha channel against black background

graphicsModePreBlackAlpha

Premultiplied with alpha channel against white background

graphicsModePreWhiteAlpha

Premultiplied with alpha channel against other color

graphicsModePreMulColorAlpha; color indicated in kQTAlphaModePreMulColor value

The depth value of 32 in an image description indicates the presence of an alpha channel.

Extracted TIFF and Exif Metadata

The TIFF graphics importer can extract metadata from a variety of TIFF tags for which QuickTime does not have standard user data type codes. Rather than define an individual code for each TIFF tag imported in this way, the graphics importer constructs user data type codes from the TIFF tags by adding the TIFF tag values (which are unsigned 2-byte integers) to defined prefix values (which fill in the two most significant bytes).

The following fields in the main TIFF directory are translated to standard QuickTime user data types:

TIFF Field

User Data Type

DocumentName

kUserDataTextFullName

ImageDescription

kUserDataTextInformation

Make

kUserDataTextMake

Model

kUserDataTextModel

Software

kUserDataTextSoftware

DateTime

kUserDataTextCreationDate

Artist

kUserDataTextArtist

HostComputer

kUserDataTextHostComputer

Copyright

kUserDataTextCopyright

IPTC (0x8469)

kUserDataIPTC

The following fields in the main TIFF directory are translated to user data using the prefix value kQTTIFFUserDataPrefix:

In Exif TIFF files, all fields in the Exif directory are translated to user data using the prefix value kQTTIFFExifUserDataPrefix. All fields in a GPS directory are translated to user data using the prefix value kQTTIFFExifGPSUserDataPrefix.

The TIFF graphics exporter also supports storing the following user data types in exported TIFF files:

User Data Type TIFF Field

kUserDataTextFullName DocumentName

kUserDataTextInformation ImageDescription

kUserDataTextMake Make

kUserDataTextModel Model

kUserDataTextArtist Artist

kUserDataTextCopyright Copyright

Software, DateTime, and HostComputer are written automatically.

In Exif mode, the TIFF graphics exporter will also write tags defined in the Exif version 2.1 specification by reversing the kQTTIFFExifUserDataPrefix and kQTTIFFExifGPSUserDataPrefix mappings.

In Exif mode, the JPEG graphics exporter supports all the same metadata fields as the TIFF graphics exporter.

Note that UserData item data is always stored big-endian. The TIFF graphics importer and graphics exporter perform whatever translation is necessary.

New APIs For Creating Exif Files

The following are a group of new APIs available on Mac OS X, Mac OS 9, and Windows for creating Exif files.

GraphicsExportSetExifEnabled

Sets whether or not the graphics exporter component should create Exif files.

ComponentResult GraphicsExportSetExifEnabled (GraphicsExportComponent ci,
   Boolean enableExif );

Parameters
ci

The component instance that identifies your connection to the graphics exporter component.

enableExif

Indicates whether to turn Exif export on or off.

Discussion

Turning on Exif export disables incompatible settings, such as grayscale JPEG and compressed TIFF, and enables export of Exif metadata. Use the GraphicsExportSetMetaData routine to supply Exif metadata.

This routine is only supported by the TIFF and JPEG graphics exporters.

Availability
Declared In
ImageCompression.h

GraphicsExportGetExifEnabled

Returns the current Exif export setting.

ComponentResult GraphicsExportGetExifEnabled (
   GraphicsExportComponent  ci,
   Boolean * exifEnabled );

Parameters
ci

The component instance that identifies your connection to the graphics exporter component.

enableExif

Points to a variable to receive the current Exif export setting.

Discussion

This routine is only supported by the TIFF and JPEG graphics exporters.

Availability
Declared In
ImageCompression.h

GraphicsExportSetThumbnailEnabled

Sets whether or not the graphics exporter component should create an embedded thumbnail inside the exported file.

ComponentResult GraphicsExportSetThumbnailEnabled (
   GraphicsExportComponent  ci,
   Boolean                enableThumbnail,
   long                   maxThumbnailWidth,
   long                   maxThumbnailHeight );

Parameters
ci

The component instance that identifies your connection to the graphics exporter component.

enableThumbnail

Indicates whether thumbnail creation should be turned on or off.

maxThumbnailWidth

The maximum width for created thumbnails.

maxThumbnailHeight

The maximum height for created thumbnails. If one maximum dimension is zero, only the other will be used. If both maximum dimensions are 0, the graphics exporter will decide for itself.

Discussion

This routine also sets optional maximum dimensions for the thumbnail. The graphics exporter will not change the aspect ratio of the image when creating the thumbnail; nor will it create a thumbnail larger than the image.

This routine is currently only supported by the TIFF and JPEG graphics exporters. The JPEG graphics exporter can only create thumbnails when writing Exif files.

Availability
Declared In
ImageCompression.h

GraphicsExportGetThumbnailEnabled

Returns the current thumbnail export settings.

ComponentResult GraphicsExportGetThumbnailEnabled (
   GraphicsExportComponent  ci,
   Boolean *              thumbnailEnabled,
   long *                 maxThumbnailWidth,
   long *                 maxThumbnailHeight );

Parameters
ci

The component instance that identifies your connection to the graphics exporter component.

thumbnailEnabled

Points to a variable to receive the current thumbnail setting. Pass NULL if you do not want to receive this information.

maxThumbnailWidth

Points to a variable to receive the current maximum thumbnail width. Pass NULL if you do not want to receive this information.

maxThumbnailHeight

Points to a variable to receive the current maximum thumbnail height. Pass NULL if you do not want to receive this information.

Discussion

This routine is currently only supported by the TIFF and JPEG graphics exporters.

Availability
Declared In
ImageCompression.h

Improved Movie Toolbox Support for Data Handlers

QuickTime 6 enhances the ability of third-party developers to add new types of data references through the introduction of QuickTime data handler components. These are called custom data handlers.

Background

QuickTime has always had two ways to reference storage of media data.

The first is through Mac OS-style file specification records known as FSSpec records. These FSSpec records are used by the Mac OS toolbox to reference files on disk and can describe any file in the file system.

The other type of storage reference is through a QuickTime abstraction known as a data reference. Data references are handles to blocks of data describing the location of data to be either read or written. The type of reference is described by a 4 char code (an OSType) and is used to select the QuickTime component––a data handler component––that performs the actual I/O operations.

The currently defined data handler types available with QuickTime are the following:

Note: The rAliasType data reference type manages access to files. The reference itself is an Alias handle and can describe any file describable by a FSSpec record.

Data Handlers and the New QuickTime APIs

Although the QuickTime software architecture provides rich support for both FSSpecs and data references, some APIs have not supported data references as fully as possible. This has meant that certain operations could only be performed on files described by FSSpec records. These operations, then, could not be performed with data handler components, either those provided by QuickTime or those that were custom.

This section discusses a group of new APIs in Movies.h that accept a data reference where an older call accepted an FSSpec or a data handler where a file reference.

The goal is twofold: (1) to support the writing of custom data handlers, and (2) to ensure that data references can be used wherever a File Manager API might have only existed before.

Table 1-3 describes the mapping of old calls to new calls:

Table 1-3  A mapping of old data handler calls to new data handler calls

Old Calls

New Calls

CreateMovieFile

CreateMovieStorage

OpenMovieFile

OpenMovieStorage

CloseMovieFile

CloseMovieStorage

DeleteMovieFile

DeleteMovieStorage

AddMovieResource

AddMovieToStorage

UpdateMovieResource

UpdateMovieInStorage

PutMovieIntoDataFork64

PutMovieIntoStorage

NewMovieFromDataFork64

NewMovieFromStorageOffset

PutMovieIntoStorage

Writes a movie in a given file managed by the data handler.

OSErr PutMovieIntoStorage ( Movie theMovie,
DataHandler dh,
const wide *offset,
unsigned long maxSize );

Parameters
theMovie

A movie identifier. Your application obtains this identifier from such functions as NewMovie (II–1098), NewMovieFromFile (II–1110), and NewMovieFromHandle (II–1113).

dh

A data handler for the data fork of the given storage. You pass in an open write path in the dh parameter.

offset

A pointer to a value that indicates where the movie should be written.

maxSize

The largest number of bytes that may be written.

Return Value

You can access Movie Toolbox error returns through GetMoviesError (I–505) and GetMoviesStickyError (I–506), as well as in the function result. See “Error Codes” (IV–2718).

Discussion

If you are writing a custom data handler, make sure that the following data handler APIs are implemented:

Introduced in QuickTime 6.

Availability
Declared In
Movies.h

C interface file: Movies.h

CreateMovieStorage

Creates an empty storage to hold the movie which references the data reference, and opens a data handler to the movie file with write permission.

   
CreateMovieStorage (Handle dataRef,
OSType dataRefType,
OSType creator,
ScriptCode scriptTag,
long createMovieFileFlags,
DataHandler * outDataHandler,
Movie * newmovie);

Parameters
dataRef

A data reference to the storage for the movie file to be created.

dataRefType

The type of data reference.

creator

The creator value for the new file.

scriptTag

The script in which the movie file should be created. Use the Script Manager constant smSystemScript to use the system script; use the smCurrentScript constant to use the current script.

createMovieFileFlags

Controls movie file creation flags (see below).

createMovieFileDeleteCurFile

Indicates whether to delete an existing file. If you set this flag to 1, the Movie Toolbox deletes the file (if it exists) before creating the new movie file. If you set this flag to 0 and the file specified by the dataRef parameter already exists, the Movie Toolbox uses the existing file.

createMovieFileDontCreateMovie

Controls whether CreateMovieStorage creates a new movie in the movie file. If you set this flag to 1, the Movie Toolbox does not create a movie in the new movie file. In this case, the function ignores the newmovie parameter. If you set this flag to 0, the Movie Toolbox creates a movie and returns the movie identifier in the field referred to by the newmovie parameter.

createMovieFileDontOpenFile

Controls whether CreateMovieStorage opens the new movie file. If you set this flag to 1, the Movie Toolbox does not open the new movie file. In this case, the function ignores the outDataHandler parameter. If you set this flag to 0, the Movie Toolbox opens the new movie file and returns an instance of a data handler in the outDataHandler parameter.

newMovieActive

Controls whether the new movie is active. Set this flag to 1 to make the new movie active. A movie that does not have any tracks can still be active. When the Movie Toolbox tries to play the movie, no images are displayed, because there is no movie data. You can make a movie active or inactive by calling SetMovieActive (III–1654).

newMovieDontAutoAlternate

Controls whether the Movie Toolbox automatically selects enabled tracks from alternate track groups. If you set this flag to 1, the Movie Toolbox does not automatically select tracks for the movie; you must enable tracks yourself.

outDataHandler

A pointer to a field that is to receive the data handler for the opened movie file. Your application must use this value when calling other Movie Toolbox functions that work with movie files. If you set this parameter to NIL, the Movie Toolbox creates the movie file but does not open the file.

newmovie

A pointer to a field that is to receive the identifier of the new movie. CreateMovieStorage returns the identifier of the new movie. If the function could not create a new movie, it sets this returned value to NIL. If you set this parameter to NIL, the Movie Toolbox does not create a movie.

You can access Movie Toolbox error returns through GetMoviesError (I–505) and GetMoviesStickyError (I–506), as well as in the function result. See “Error Codes” (IV–2718).

Discussion

If you are writing a custom data handler, make sure that the following data handler APIs are implemented:

Introduced in QuickTime 6.

Availability
Declared In
Movies.h

C interface file: Movies.h

OpenMovieStorage

Opens a data handler that specifies movie storage.

OpenMovieStorage (Handle dataRef,
OSType dataRefType,
long flags,
DataHandler * outDataHandler);

Parameters
dataRef

A data reference to a handle for the movie to be stored.

dataRefType

The type of data reference.

flags

(See below.)

outDataHandler

A pointer to a field that is to receive the data handler for the opened movie file. Your application must use this value when calling other Movie Toolbox functions that work with movie files.

Flags:

kDataHCanRead
kDataHCanWrite
Discussion

This routine is rarely used.

Introduced in QuickTime 6.

Availability
Declared In
Movies.h

C interface file: Movies.h

CloseMovieStorage

Closes an open movie storage.

CloseMovieStorage (DataHandler dh);

Parameters
dh

A data handler.

Discussion

This routine is equivalent to CloseComponent.

Introduced in QuickTime 6.

Availability
Declared In
Movies.h

C interface file: Movies.h