Standard Audio - The CodecSpecificSettingsArray and MagicCookie properties

Q: I want to use the StdAudio dialog to configure an AudioConverter but I'm not sure what to do with the kQTSCAudioPropertyID_CodecSpecificSettingsArray property. What is the corresponding Core Audio Audio Converter property and is this property required?

A: Depending on format selected in the Standard Compression Dialog (see Figure 1), two properties may be available and required to correctly configure a Core Audio AudioConverter and output file (if one is being created) to store the converted audio data.

Figure 1: Standard Audio Compression Component Dialog.

Figure 1, Standard Audio Compression Component Dialog.

The first is the Codec Specific Settings Array and the second is the Magic Cookie. These two properties are represented by different constants when used with QuickTime and Core Audio APIs however, there is no difference in the property values they represent.

Codec Specific Settings Array

Table 1:

Standard Audio (QuickTimeComponents.h)Audio Converter (AudioConverter.h)
kQTSCAudioPropertyID_CodecSpecificSettingsArraykAudioConverterPropertySettings

Some (but not all) audio codecs publish settings as a CFDictionaryRef describing various parameters that are only specific to the codec being configured.

Additionally, every subconverter used by an Audio Converter can potentially have a CFDictionaryRef of settings. For example, when performing a sample rate conversion from PCM to PCM there will be a dictionary exposed by a rate converter subconverter. The Audio Converter used in such a conversion operation will conglomerate the various CFDictionaryRef's exposed by its subconverters in the CFArrayRef returned as the CodecSpecificSettingsArray property.

When working with Standard Audio, this property is retrieved and set by calling the QTGetComponentProperty / QTSetComponentProperty API pair using the kQTSCAudioPropertyID_CodecSpecificSettingsArray property ID.

When configuring an audio converter, the codec specific settings array retrieved from StdAudio is set by calling AudioConverterSetProperty using the kAudioConverterPropertySettings property ID.

Applications wishing to provide a custom user interface for audio codecs supporting this property may parse the returned CFArrayRef using the Audio Codec Property Settings keys available in AudioCodec.h.

When individual values in this array are modified, a client must call QTSetComponentProperty and pass in the entire array.

Back to Top 

Magic Cookie

Table 2:

Standard Audio (QuickTimeComponents.h)Audio Converter (AudioConverter.h)
kQTSCAudioPropertyID_MagicCookiekAudioConverterCompressionMagicCookie

Some (but not all) audio codecs provide a variable sized "blob" of untyped (void *) configuration data. This "out of band" data is required to process the stream of encoded audio correctly. This data is considered private to the codec.

When working with Standard Audio this property is retrieved and set by calling the QTGetComponentProperty / QTSetComponentProperty API pair using the kQTSCAudioPropertyID_MagicCookie property ID. You need to allocate a buffer to hold this data, therefore before calling QTGetComponentProperty to retrieve the magic cookie a call to QTGetComponentPropertyInfo is required to get the size, allocate a buffer of the specified size then call QTGetComponentProperty passing in the newly allocated buffer (see Listing 1).

When configuring an audio converter the magic cookie retrieved from StdAudio is set by calling AudioConverterSetProperty using the kAudioConverterCompressionMagicCookie property ID.

Note: An audio converter may require further setup depending on the format conversion being performed, for example a kAudioConverterDecompressionMagicCookie property may be required. For more information refer to the Core Audio documentation and sample code provided in the Core Audio SDK.

Back to Top 

Core Audio AudioConverter Configuration

The rules for using the above two properties to configure a Core Audio AudioConverter are straight forward:

  • When querying StdAudio, applications should always ask for both the CodecSpecificSettingsArray and the MagicCookie.

  • When configuring a Core Audio AudioConverter, the CodecSpecificSettingsArray should be preferred if both properties are available.

  • If the CodecSpecificSettingsArray is NOT available use the MagicCookie if available.

IMPORTANT: If a MagicCookie is available, it will always be required when creating a Sound Description (using QTSoundDescriptionCreate) or when using the AudioFile API if the intent is to write the converted audio data to a file, for example a QuickTime movie file (.mov) or a Core Audio file (.caf) and so on.

Listing 1: Snippet for getting and setting properties discussed.

ComponentInstance ci = 0;
AudioConverterRef myAudioConverter = NULL;

CFArrayRef codecSpecificSettings = NULL;
UInt32 magicCookieSize = 0;
void * magicCookie = NULL;

UInt32 flags;

// open StdAudio (added in QuickTime 7.0)
err = OpenADefaultComponent(StandardCompressionType, StandardCompressionSubTypeAudio, &ci);
if (err) goto bail;

// set some configuration properties before bringing up the dialog
// such as input ASBD, input channel layout and so on
...

// show the dialog (this call blocks until the dialog is finished)
err = SCRequestImageSettings(ci);
if (err) goto bail;

// get the configuration properties specified in the dialog
...

// get the codec specific settings if available
if (noErr == QTGetComponentPropertyInfo(ci,
                                        kQTPropertyClass_SCAudio,
                                        kQTSCAudioPropertyID_CodecSpecificSettingsArray,
                                        NULL, NULL, &flags) && (flags &
                                        kComponentPropertyFlagCanGetNow)) {

    err = QTGetComponentProperty(ci, kQTPropertyClass_SCAudio,
                                     kQTSCAudioPropertyID_CodecSpecificSettingsArray,
                                     sizeof(CFArrayRef), &mCodecSpecificSettings, NULL);
    if (err) goto bail;
}

// get the magic cookie if available
if (noErr == QTGetComponentPropertyInfo(ci,
                                        kQTPropertyClass_SCAudio,
                                        kQTSCAudioPropertyID_MagicCookie,
                                        NULL, &magicCookieSize, NULL) &&
                                        magicCookieSize) {

    magicCookie = calloc(1, magicCookieSize);
    if (NULL == mMagicCookie) { err = memFullErr; goto bail; }

    err = QTGetComponentProperty(ci, kQTPropertyClass_SCAudio,
                                     kQTSCAudioPropertyID_MagicCookie,
                                     magicCookieSize, magicCookie, &magicCookieSize);
    if (err) goto bail;
}

// get more properties as appropriate
...

// once we have all the required properties close StdAudio
CloseComponent(ci); ci = 0;

 // create an AudioConverter
err = AudioConverterNew(&myInputASBD, &myOutputASBD, &myAudioConverter);
if (err) goto bail;

// set other Audio Converter properties such as channel layout and so on
...

// a codec that has CodecSpecificSettings may have a MagicCookie
// prefer the CodecSpecificSettingsArray if you have both
if (NULL != codecSpecificSettings) {

    err = AudioConverterSetProperty(myAudioConverter,
                                    kAudioConverterPropertySettings,
                                    sizeof(CFArray),
                                    codecSpecificSettings);
    if (err) goto bail;

    CFRelease(codecSpecificSettings);

} else if (NULL != magicCookie) {
    err = AudioConverterSetProperty(myAudioConverter,
                                    kAudioConverterCompressionMagicCookie,
                                    magicCookieSize,
                                    magicCookie);
    if (err) goto bail;

    // we may need the magic cookie later if we're going to write the data to a file
    // but make sure and remember to free it when we're done!
}

// continue with any other required setup
...

bail:
    if (err) {
        If (codecSpecificSettings) CFRelease(codecSpecificSettings);
        if (magicCookie) free(magicCookie);
        if (ci) CloseComponent(ci);
        if (myAudioConverter) AudioConverterDispose(myAudioConverter);

        // clean up as required
        ...
    }

return err;

Back to Top 

References:

Back to Top 

Document Revision History

DateNotes
2006-11-16First Version

Posted: 2006-11-16


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.